Подсчет строк игнорируется grep - PullRequest
3 голосов
/ 01 декабря 2011

Позвольте мне попытаться объяснить это как можно яснее ...

У меня есть скрипт, который в какой-то момент делает это:

grep -vf ignore.txt input.txt

Этот ignore.txt имеет кучустрок с вещами, которые я хочу, чтобы мой grep игнорировал, отсюда -v (то есть я не хочу видеть их в выводе grep).

Теперь я хочу узнать, сколько строк input.txt было проигнорировано каждой строкой ignore.txt.

Например, если ignore.txt имеет следующие строки:

line1
line2
line3

Я хотел бы знать, сколько строк input.txt было проигнорировано игнорированием line1, сколько - игнорированием line2,и т. д.

Есть идеи, как мне это сделать?

Надеюсь, это имело смысл ... Спасибо!

Ответы [ 7 ]

1 голос
/ 01 декабря 2011

Обратите внимание, что сумма пропущенных строк плюс показанные строки НЕ МОЖЕТ сложиться с общим числом строк ... "line1 и line2 are here" будут подсчитаны дважды.

0 голосов
/ 01 декабря 2011
while IFS= read -r pattern ; do
        printf '%s:' "$pattern"
        grep -c -v "$pattern" input.txt
done < ignore.txt

grep с -c подсчитывает совпадающие строки, но с добавлением -v подсчитывает несовпадающие строки. Итак, просто зациклите шаблоны и посчитайте один раз для каждого шаблона.

0 голосов
/ 01 декабря 2011

Будет напечатано количество пропущенных совпадений вместе с шаблоном совпадения:

grep -of ignore.txt input.txt | sort | uniq -c

Например:

$ perl -le 'print "Coroline" . ++$s for 1 .. 21' > input.txt
$ perl -le 'print "line2\nline14"'               > ignore.txt

$ grep -of ignore.txt input.txt | sort | uniq -c
      1 line14
      3 line2

Т.е. строка, совпадающая с "line14", была проигнорирована один раз.Строка, совпадающая с «line2», игнорировалась 3 раза.

Если вы просто хотите подсчитать общее количество игнорируемых строк, это будет работать:

grep -cof ignore.txt input.txt 

Обновление: изменил пример выше, чтобы использовать строки так,что вывод немного яснее.

0 голосов
/ 01 декабря 2011

Сортируются ли ignore.txt и input.txt?

Если это так, вы можете использовать команду comm !

$ comm -12 ignore.txt input.txt

Сколько строк игнорируется?

$ comm -12 ignore.txt input.txt | wc -l

Или, если вы хотите сделать больше обработки, объедините comm с awk.:

$ comm ignore.txt input.txt | awk '
    END {print "Ignored lines = " igtotal " Lines not ignored = "commtotal " Lines unique to Ignore file = " uniqtotal}
    {
       if ($0 !~ /^\t/) {uniqtotal+=1}
       if ($0 ~ /^\t[^\t]/) {commtotal+=1}
       if ($0 ~ /^\t\t/) {igtotal+=1}
    }'

Здесь я воспользуюсь вкладками, которыепомещается в вывод командой comm: * Если вкладок нет, строка находится только в ignore.txt.* Если имеется одна вкладка, она есть только в файле input.txt * Если есть две вкладки, строка находится в обоих файлах.

Кстати, не все строки в ignore.txt игнорируются.Если эта строка также отсутствует в файле input.txt, ее нельзя сказать игнорируемой .

С предложением Денниса Уильямсона

comm ignore.txt input.txt | awk '
   !/^\t/ {uniqtotal++}
   /^\t[^\t]/ {commtotal++}
   /^\t\t/ {igtotal++}
     END {print "Ignored lines = " igtotal " Lines not ignored = "commtotal " Lines unique to Ignore file = " uniqtotal}'
0 голосов
/ 01 декабря 2011

Этот скрипт будет подсчитывать совпавшие строки путем поиска в хэш-памяти и сохранит строки, которые будут напечатаны в @result, где вы можете обработать их, как хотите. Чтобы подражать grep, просто распечатайте их.

Я сделал скрипт, чтобы он мог распечатать пример. Чтобы использовать с файлами, раскомментируйте код в скрипте и прокомментируйте те, которые отмечены # example line.

Код:

use strict;
use warnings;
use v5.10;
use Data::Dumper;  # example line

# Example data. 
my @ignore = ('line1' .. 'line9'); # example line
my @input  = ('line2' .. 'line9', 'fo' .. 'fx', 'line2', 'line3'); # example line

#my $ignore = shift;  # first argument is ignore.txt
#open my $fh, '<', $ignore or die $!; 
#chomp(my @ignore = <$fh>);
#close $fh;

my @result;

my %lookup = map { $_ => 0 } @ignore;
my $rx = join '|', map quotemeta, @ignore;

#while (<>) {  # This processes the remaining arguments, input.txt etc
for (@input) { # example line
    chomp;     # Required to avoid bugs due to missing newline at eof
    if (/($rx)/) {
        $lookup{$1}++;
    } else {
        push @result, $_;
    }
}

#say for @result;       # This will emulate grep
print Dumper \%lookup;  # example line

Выход:

$VAR1 = {
          'line6' => 1,
          'line1' => 0,
          'line5' => 1,
          'line2' => 2,
          'line9' => 1,
          'line3' => 2,
          'line8' => 1,
          'line4' => 1,
          'line7' => 1
        };
0 голосов
/ 01 декабря 2011

Это может работать для вас:

# seq 1 15 | sed '/^1/!d' | sed -n '$='
7

Объяснение:

Удалить все строки, кроме совпадающих.Передайте эти совпадающие (игнорируемые) строки в другую команду sed.Удалите все эти строки, но покажите номер строки только последней строки.Таким образом, в этом примере с 1 по 15 строки 1,10 - 15 игнорируются - всего 7 строк.

РЕДАКТИРОВАТЬ:

Извините, неправильно прочитал вопрос (все еще немного сбит с толку!):

 sed 's,.*,sed "/&/!d;s/.*/matched &/" input.txt| uniq -c,' ignore.txt | sh

Показывает номер matches для каждого шаблона в ignore.txt

 sed 's,.*,sed "/&/d;s/.*/non-matched &/" input.txt | uniq -c,' ignore.txt | sh

Показывает номер non-matches для каждого шаблона в ignore.txt

Если используется GNU sed, они также должны работать:

sed 's,.*,sed "/&/!d;s/.*/matched &/" input.txt | uniq -c,;e' ignore.txt

или

sed 's,.*,sed "/&/d;s/.*/non-matched &/" input.txt | uniq -c,;e' ignore.txt

NB Ваш успех с шаблонами может отличаться, т.е. заранее проверьте метасимволы.

При отражении я подумал, что это можно улучшить до:

sed 's,.*,/&/i\\matched &,;$a\\d' ignore.txt | sed -f - input.txt | sort -k2n | uniq -c

или

sed 's,.*,/&/!i\\non-matched &,;$a\\d' ignore.txt | sed -f - input.txt | sort -k2n | uniq -c

Но НЕТ, для больших файлов это на самом деле медленнее.

0 голосов
/ 01 декабря 2011

Согласно unix.stackexchange

grep -o pattern file | wc -l

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

Однако я бы попытался создать более удобное решение с использованием языка сценариев, например, например. питон.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...