grep redirect не соответствует - PullRequest
       25

grep redirect не соответствует

3 голосов
/ 26 января 2011

Я делаю простой grep для строк, начинающихся с таких шаблонов, как:

grep -E "^AAA" myfile > newfile

Я также хотел бы (в том же направлении) перенаправить эти несовпадающие строки в другой файл.
Я знаю, что можно было бы просто сделать это дважды и использовать -v во второй попытке, но файлы (относительно) огромны, и только чтение их один раз сэкономило бы довольно ценное время ...

Я думал о перенаправлении несоответствия к stderr, как:

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

Этот трюк как-то возможен с grep или мне лучше просто написать его?

(может иметь дополнительное значение - я кодирую это в скрипте bash)

Ответы [ 5 ]

4 голосов
/ 26 января 2011

Это будет работать:

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
2 голосов
/ 26 января 2011

Я не верю, что это можно сделать с помощью 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)

(Оба абсолютно не проверены. Ваш пробег может отличаться. Недействительно там, где это запрещено.)

2 голосов
/ 26 января 2011

Боюсь, это невозможно. Я бы использовал Perl и сделал бы что-то вроде:

if (/^AAA/) {
   print STDOUT $_;
}
else
{
   print STDERR $_;
}
1 голос
/ 29 сентября 2016

Вы можете использовать подстановку процесса для дублирования канала во время чтения файла (вдохновение https://unix.stackexchange.com/a/71511). Это должно быть почти так же эффективно, поскольку файл все еще читается только один раз.

Что-товот так должно работать:

cat file.txt | tee >(grep 'pattern' > matches.txt) | grep -v 'pattern' > non-matches.txt

0 голосов
/ 14 мая 2015

Вот функция для вас:

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...