Как получить имя входного файла в однострочном Perl?

кошка понедельник.csv

223.22;1256.4
227.08;1244.8
228.08;1244.7
229.13;1255.0
227.89;1243.2
224.77;1277.8

кот вторник.csv

227.02;1266.3
227.09;1234.9
225.18;1244.7
224.13;1255.3
228.59;1263.2
224.70;1247.6

Этот однострочник Perl дает мне строку с наибольшим значением во втором столбце из строк, где в первом столбце первые 3 цифры равны 227 или 226 из файла "monday.csv":

$ perl -F\; -ane '$hash{$_} = $F[1] if /22[78]/; END{ print and exit for sort{ $hash{$b} <=> $hash{$a} } keys %hash }' monday.csv

Этот однострочник Perl дает мне строку с наибольшим значением во втором столбце из строк, где в первом столбце первые 3 цифры равны 227 или 226 из всех файлов *day.csv:

$ perl -F\; -ane '$hash{$_} = $F[1] if /22[78]/; END{ print and exit for sort{ $hash{$b} <=> $hash{$a} } keys %hash }' *day.csv

Как я мог бы переписать этот однострочный код, чтобы получить результат:

имя файла: "строка с наибольшим значением во втором столбце из строк, где в первом столбце первые 3 цифры равны 227 или 226 из файла 'filename.csv'"

для каждого *day.csv файла?


person sid_com    schedule 16.10.2010    source источник


Ответы (4)


Вы можете использовать $ARGV для текущего имени файла. Если вас интересует только максимальное значение, нет необходимости сохранять все значения, а затем сортировать их; вместо этого просто сохраните максимум для каждого файла. Кроме того, ваше регулярное выражение, вероятно, должно быть привязано к началу строки.

# Line breaks added for display purposes.
perl -F\; -ane '
    $max{$ARGV} = $F[1] if /^22[78]/ and $F[1] > $max{$ARGV};
    END{ print "$_\t$max{$_}" for sort keys %max}
' *day.csv

Или, если вы хотите сохранить всю строку, где встречается максимум:

perl -F\; -ane '
    ($max{$ARGV}{ln}, $max{$ARGV}{mx}) = ($_, $F[1])
        if /^22[78]/ and $F[1] > $max{$ARGV}{mx};
    END{ print "$_\t$max{$_}{ln}" for sort keys %max}
' *day.csv
person FMc    schedule 16.10.2010

Имя файла содержится в переменной $ARGV:

$ARGV

содержит имя текущего файла при чтении из ‹>.


Однако у представленных острот есть проблема; что делать, если у вас есть повторяющиеся значения вашего первого столбца?

Лучшим однострочным было бы:

$ perl -F/;/ -MList::Util=max -lane 'push @{ $wanted{$ARGV} }, $F[1] if $F[0] =~ /22[78]/; } END { print "$ARGV : ", max(@{ $wanted{$_} }) for keys %wanted;' *.csv

На основании комментария:

$ perl -F/;/ -lane '$wanted{$ARGV} = \@F if $F[1] >= $wanted->{$ARGV}[1] && $F[0] =~ /22[78]/; } END { print "$_ : @$wanted{$_}" for keys %wanted;' *.csv
person Zaid    schedule 16.10.2010
comment
Я не вижу проблемы с повторяющимися значениями. - person sid_com; 16.10.2010
comment
в первом столбце. Но я вижу проблему с повторяющимися значениями во втором столбце. Причина в том, забыл упомянуть, что я хотел бы иметь последнее значение в файле из самых высоких значений, если в файле более одного самого высокого значения. - person sid_com; 17.10.2010
comment
Но я думаю, что во второй строчке много ошибок. - person sid_com; 17.10.2010

Кажется, вы можете использовать $ARGV. См. "текущее имя файла"

person Aif    schedule 16.10.2010

Если бы я хотел всю строку, я мог бы сделать это (на основе ответа FM):

perl -F\; -ane '$max{$ARGV} = $_ if /^22[78]/ and $F[1] >= (split /;/, $max{$ARGV})[1];  END{ print "$_\t$max{$_}" for sort keys %max}' *day.csv

Я нашел более короткое решение.
все файлы:

perl -F\; -anE '$max{$ARGV} = [@F] if /^22[78]/ and $F[1] >= $max{$ARGV}->[1];  END{ print "$_\t@{$max{$_}}" for sort keys %max}' *day.csv

один файл:

perl -F\; -anE '$max = [@F] if /^22[78]/ and $F[1] >= $max->[1]; END{ print "@$max" }' monday.csv

или если места мало

perl -F\; -anE'$m{$ARGV}=[@F]if/^22[78]/&&$F[1]>=$$m{$ARGV}[1]}print"$_\t@{$m{$_}}"for sort keys%m;{' *day.csv

perl -F\; -anE'$m=[@F]if/^22[78]/&&$F[1]>=$$m[1]}print"@$m";{' monday.csv

Как показал Зайд: чтобы получить последнюю строку с наивысшим значением в случае повторения наивысших значений в файле, я изменил часть «$F[1] > $max...» на «$F[1] >= $ Максимум".

person sid_com    schedule 16.10.2010