Perl grep через большой файл, чтобы сопоставить строку - PullRequest
0 голосов
/ 25 мая 2020

У меня есть массив (@array) со списком элементов. Мне нужно проверить, существует ли каждый из этих элементов в главном файле или нет. Если элемент существует в мастер-файле, то в той же строке мастер-файла должна существовать строка YES (в 5-й позиции). И элемент должен храниться в другом массиве.

На самом деле мой скрипт использует две grep команды оболочки для достижения этого. Как я могу написать то же самое в Perl do grep.

...
use Data::Dumper;

my @new_array;
my @array = ('RT0AC1', 'WG3RA3');

print Dumper(\@array);

foreach ( @array ){
    my $line = `grep $_ "master_file.csv" | grep -i yes`;
    next unless($line);
    push( @new_array, $_ );
}

print Dumper(@new_array);
...

где master_file.csv выглядит так:

101,RT0AC1,CONNECTED,FAULTY,NO
102,RT0AC1,CONNECTED,WORKING,YES
103,RT0AC1,NOT CONNECTED,WORKING,NO
104,WG3RA3,NOT CONNECTED,DISABLED,NO
105,WG3RA3,CONNECTED,WORKING,NO

Итак, здесь я получаю $line значение как 102,RT0AC1,CONNECTED,WORKING,YES и элемент RT0AC1 сохраняется в @new_array.

Как мне избежать использования обратной кавычки (`) и двух greps для достижения этой цели. Я пытаюсь сделать это с помощью чистого Perl. Также master_file.csv содержит миллионы записей.

Ответы [ 2 ]

2 голосов
/ 25 мая 2020

Так как все слова, которые вы ищете, находятся в одном месте, легко просто разделить текущую строку на запятые и посмотреть, существует ли второй столбец в таблице ha sh, а пятый столбец - это равно "YES":

#!/usr/bin/env perl
use strict;
use warnings;
use autodie;
use Data::Dumper;

my $filename = shift // "master_file.csv"; # Default filename if not given on command line
my @array = qw/RT0AC1 WG3RA3/; # Words you're looking for
my %words = map { $_ => 1 } @array; # Store them in a hash for fast lookup
my @new_array;

# Use Text::CSV_XS for non-trivial CSV files
open my $csv, "<", $filename;
while (<$csv>) {
    chomp;
    my @F = split /,/;
    push @new_array, $F[1] if exists $words{$F[1]} && $F[4] eq "YES";
}

print Dumper(\@new_array);
0 голосов
/ 25 мая 2020

Форма регулярное выражение для сопоставления интересующих записей, разделение строки на поля и сравнение поля № 5 с ДА . Если есть совпадение, увеличьте счетчик для поля № 2 в %match ha sh.

После обработки файла %match ha sh будет иметь совпадающие записи в поле № 2 в качестве ключа и значения отражает , сколько раз это поле совпадало с ДА в файле.

use strict;
use warnings;
use feature 'say';

use Data::Dumper;

my %match;
my @look_for = qw(RT0AC1 WG3RA3);
my $re_filter = join('|',@look_for);

while(<DATA>) {
    chomp;
    next unless /$re_filter/;
    my @data = split(',',$_);
    $match{$data[1]}++ if $data[4] eq 'YES';
}

say Dumper(\%match);

__DATA__
101,RT0AC1,CONNECTED,FAULTY,NO
102,RT0AC1,CONNECTED,WORKING,YES
103,RT0AC1,NOT CONNECTED,WORKING,NO
104,WG3RA3,NOT CONNECTED,DISABLED,NO
105,WG3RA3,CONNECTED,WORKING,NO

Вывод

$VAR1 = {
          'RT0AC1' => 1
        };

Удалить DATA чтобы получить окончательный код и указать имя файла в командной строке для обработки файла с интересующими данными

use strict;
use warnings;
use feature 'say';

use Data::Dumper;

my %match;
my @look_for = qw(RT0AC1 WG3RA3);
my $re_filter = join('|',@look_for);

while(<>) {
    chomp;
    next unless /$re_filter/;
    my @data = split(',',$_);
    $match{$data[1]}++ if $data[4] eq 'YES';
}

say Dumper(\%match);

Альтернативная версия на основе регулярного выражения без использования split

use strict;
use warnings;
use feature 'say';

use Data::Dumper;

my %match;
my @look_for  = qw(RT0AC1 WG3RA3);
my $re_filter = join('|',@look_for);
my $regex     = qr/^\d+,($re_filter),[^,]+,[^,]+,YES$/;

/$regex/ && $match{$1}++ for <DATA>;

say Dumper(\%match);

__DATA__
101,RT0AC1,CONNECTED,FAULTY,NO
102,RT0AC1,CONNECTED,WORKING,YES
103,RT0AC1,NOT CONNECTED,WORKING,NO
104,WG3RA3,NOT CONNECTED,DISABLED,NO
105,WG3RA3,CONNECTED,WORKING,NO
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...