grep重定向不匹配

时间:2011-01-26 16:54:02

标签: bash file command-line grep

对于以某些模式开头的行,我正在做一个简单的 grep

grep -E "^AAA" myfile > newfile

我也希望(同时)将那些不匹配的行重定向到另一个文件 我知道可以简单地做两次并在第二次尝试中使用 -v ,但文件(相对)很大,只读一次就可以节省一些非常宝贵的时间... < / p>

我正在考虑将非匹配重定向到stderr的行:

grep -E -magic_switch "^AAA" myfile > newfile 2> newfile.nonmatch

grep 这种技巧在某种程度上是可行的,还是我应该只编码呢?

(可能有额外的价值 - 我用bash脚本编码)

5 个答案:

答案 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