对于以某些模式开头的行,我正在做一个简单的 grep :
grep -E "^AAA" myfile > newfile
我也希望(同时)将那些不匹配的行重定向到另一个文件 我知道可以简单地做两次并在第二次尝试中使用 -v ,但文件(相对)很大,只读一次就可以节省一些非常宝贵的时间... < / p>
我正在考虑将非匹配重定向到stderr的行:
grep -E -magic_switch "^AAA" myfile > newfile 2> newfile.nonmatch
grep 这种技巧在某种程度上是可行的,还是我应该只编码呢?
(可能有额外的价值 - 我用bash脚本编码)
答案 0 :(得分:4)
这将有效:
awk '/pattern/ {print; next} {print > "/dev/stderr"}' inputfile
或
awk -v matchfile=/path/to/file1 -v nomatchfile=/path/to/file2 '/pattern/ {print > matchfile; next} {print > nomatchfile}' inputfile
或
#!/usr/bin/awk -f
BEGIN {
pattern = ARGV[1]
matchfile = ARGV[2]
nomatchfile = ARGV[3]
for (i=1; i<=3; i++) delete ARGV[i]
}
$0 ~ pattern {
print > matchfile
next
}
{
print > nomatchfile
}
像这样调用最后一个:
./script.awk regex outputfile1 outputfile2 inputfile
答案 1 :(得分:2)
我担心这可能是不可能的。我会使用Perl并执行以下操作:
if (/^AAA/) {
print STDOUT $_;
}
else
{
print STDERR $_;
}
答案 2 :(得分:2)
我不相信grep
可以做到这一点,但它只有几行Perl:
#! /usr/bin/perl
# usage: script regexp match_file nomatch_file < input
my $regexp = shift;
open(MATCH, ">".shift);
open(NOMATCH, ">".shift);
while(<STDIN>) {
if (/$regexp/o) {
print MATCH $_;
} else {
print NOMATCH $_;
}
}
或Python,如果您愿意:
#! /usr/bin/python
# usage: script regexp match_file nomatch_file < input
import sys
import re
exp = re.compile(sys.argv[1])
match = open(sys.argv[2], "w")
nomatch = open(sys.argv[3], "w")
for line in sys.stdin:
if exp.match(line): match.write(line)
else: nomatch.write(line)
(两者都未经测试。您的里程可能会有所不同。禁止使用的地方。)
答案 3 :(得分:1)
您可以在读取文件时使用进程替换来复制管道(灵感https://unix.stackexchange.com/a/71511)。这几乎应该是高效的,因为文件仍然只被读取一次。
这样的事情应该有效:
cat file.txt | tee >(grep 'pattern' > matches.txt) | grep -v 'pattern' > non-matches.txt
答案 4 :(得分:0)
以下是您的功能:
function perg {
awk '{y = $0~z ? "out" : "err"; print > "/dev/std" y}' z="$1" "$2"
}
将其与文件一起使用
perg ^AAA myfile > newfile 2> newfile.nonmatch
或从管道
cat myfile | perg ^AAA > newfile 2> newfile.nonmatch