grep 重定向不匹配项

5

我正在进行一个简单的grep,查找以某个模式开头的行,例如:

grep -E "^AAA" myfile > newfile

我希望在同一步骤中将不匹配的行重定向到另一个文件。
我知道可以简单地做两次并在第二次尝试中使用 -v ,但这些文件(相对而言)非常庞大,只读取它们一次将节省一些非常宝贵的时间...
我正在考虑将不匹配的内容重定向到stderr,例如:
grep -E -magic_switch "^AAA" myfile > newfile 2> newfile.nonmatch

这个技巧是否可以用grep实现,还是我应该编写代码来完成它?(可能有额外的价值 - 我是在bash脚本中编写这个)
5个回答

6

这将有效:

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

不错!我总是更喜欢使用标准工具来编写代码,而一行代码则值得额外加分 ;) - nEJC

2

我担心这可能是不可能的。我会使用Perl并执行以下操作:

if (/^AAA/) {
   print STDOUT $_;
}
else
{
   print STDERR $_;
}

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)

(两者都没有经过测试。您的使用效果可能会有所不同。在禁止的地方无效。)

谢谢!我只需要这段 Python 代码……你刚刚帮我省了五分钟的查阅时间 ;) - nEJC

2
您可以使用进程替换来在读取文件时复制管道(灵感来源于https://unix.stackexchange.com/a/71511)。这应该几乎与性能相当,因为文件仍然只被读取一次。
类似以下代码应该可以工作: cat file.txt | tee >(grep 'pattern' > matches.txt) | grep -v 'pattern' > non-matches.txt

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接