Список файлов, которые содержат менее N строк, соответствующих шаблону / строке

Я широко использую языковой модуль Perl Text::CSV_XS для сложных специальных операций с файлами CSV. Используя этот модуль, я создал четыре небольшие базовые программы Perl, чтобы использовать их в качестве строительных блоков для всего, что я хочу сделать.

  1. Filter — фильтровать inputFile filterFile field
  2. Reject — отклонять inputFile filterFile field
  3. Stripper — Stripper inputFile field [field2 field3…]
  4. Swap — Swap inputFile swapFile matchField outfield

filterFile имеет шаблон регулярного выражения на каждой строке. Все, что соответствует одному из этих шаблонов, сопоставляется в целях принятия или отклонения. Различные «поля» — это имена заголовков столбцов.

Итак, в вашем примере я просто ставлю "1" в filterFile и продолжаю:

perl Filter.pm data.csv filter.txt data_id >One.csv
perl Stripper.pm One.csv data_id event_value >Two.csv
perl Swap.pm Two.csv log.csv data_id name >Three.csv

Если бы мы также хотели, чтобы в файле событий Леопольда filter.txt имел бы две строки с одноименным содержимым:

1
2 

Я собрал мутантные версии всех четырех зданий блокировать подпрограммы, которые выполняют такие действия, как получение ввода из стандартного ввода или отправка вывода на определенный URL-адрес.

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

Во-первых, если ваши файлы огромны, вы должны использовать модуль DB_File, чтобы указать, что ваш хэш должен храниться на диске в качестве базы данных. В противном случае вы можете заполнить память и остановиться.

use DB_File;

my %theHash;
unlink '/tmp/translation.db';
sleep 2;
tie ( %theHash, 'DB_File', '/tmp/translation.db' )
    or die "Can't open /tmp/translation.db\n";

Затем создайте объекты CSV.

map{ $_ = Text::CSV_XS->new( { allow_whitespace => 1,
        eol =>"\015\012",
        always_quote => 1, binary => 1 })}
   ( $data_csv, $log_csv, $output_csv );

Обратите внимание, что я использую символы DOS EOL.

Затем извлеките строки входных заголовков, чтобы настроить имена столбцов

@cols = @{$data_csv->getline( $data_fh )};
$data_csv->column_names( @cols );
@cols = @{$log_csv->getline( $log_fh )};
$log_csv->column_names( @cols );

, где вы открыли файлы в дескрипторах файлов $data_fh и $log_fh.

Решите, какими будут выходные столбцы, и напишите строку заголовка столбца.

@output_cols = ( 'name', 'event_value' );
$output_csv->combine( @output_cols );
$latest_row = $output_csv->string();
print $output_fh, $latest_row;

Затем создайте data_id для имени хэша.

while ( $log_csv_row = $log_csv->getline_hr( $log_fh ) ){
    $theHash{ $log_csv_row->{data_id} } = $log_csv_row->{name};
}

Затем, как в вашем примере, просмотрите data.csv, чтобы получить все единицы.

$outputHash{name} = $theHash{1};

while ( $data_csv_row = $data_csv->getline_hr( $data_fh ) ){

    next unless $data_csv_row->{data_id} == 1;

    $outputHash{data_id} = $data_csv_row->{data_id};
    $output_csv->combine( map { $outputHash{$_} } @output_cols );
    $latest_row = $output_csv->string();
    print $output_fh "$latest_row";
}

Этот пример кода является основой для всех вышеперечисленных служебных подпрограмм, в которых жестко заданная «1» заменяется различными аргументами или массивами аргументов, которые помещаются в хэши.

0
27.01.2017, 13:57
2 ответа
grep -lR '226 Transfer complete\.' --include='*.log'
2
28.01.2020, 02:25

Вы можете использовать awk для подсчета вхождений и печати имени файла, если количество меньше n :

find . -type f -name \*.log -exec awk -vn=2 'BEGIN{c=0};
/PATTERN/{++c; if (c==n){exit}};END{if (c<n){print FILENAME}}' {} \;

Это остановит подсчет, как только n (в данном случае 2 ) найдены совпадения.

1
28.01.2020, 02:25

Теги

Похожие вопросы