Я широко использую языковой модуль Perl Text::CSV_XS для сложных специальных операций с файлами CSV. Используя этот модуль, я создал четыре небольшие базовые программы Perl, чтобы использовать их в качестве строительных блоков для всего, что я хочу сделать.
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» заменяется различными аргументами или массивами аргументов, которые помещаются в хэши.
Вы можете использовать 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
) найдены совпадения.