Как реализовать Unix grep в Perl?
как я могу реализовать grep
Unix в Perl? Я попытался использовать встроенный Perl grep
. Вот код, который не работает:
$pattern = @ARGV[0];
$file= @ARGV[1];
open($fp,$file);
@arr = <$fp>;
@lines = grep $pattern, @arr;
close($fp);
print @lines;
и, кстати, я пытаюсь только basic grep
функциональность не полнофункциональная, а во-вторых, я не хочу делать разбор строк сам. Я хочу использовать встроенный grep
или некоторая функция Perl.
спасибо заранее :)
5 ответов
в Perl для ссылки на весь массив мы используем @
. Но для обозначения отдельных элементов, которые являются скалярными мы используем $
.
Итак, вам нужно использовать $
, а не @
на эти строки:
$pattern = @ARGV[0];
$file= @ARGV[1];
и
этой
@lines = grep $pattern, @arr;
должно быть
@lines = grep /$pattern/, @arr;
the grep в Perl имеет общий синтаксис:
grep EXPR,LIST
он оценивает в EXPR
для каждого элемента LIST
и возвращает значение списка, состоящее из тех элементов, для которых выражение оценивается как true.
на EXPR
в вашем случае-это поиск шаблона $pattern
в массиве @arr
. Для поиска вам нужно использовать /PATTERN/
без /
строка $pattern
будет оцениваться как true или false.
конечно, ответ codaddict правильный, но я хотел бы добавить несколько замечаний:
вы всегда должны начинать свои скрипты с этих двух строк:
use strict;
use warnings;
используйте три args открыть и проверить на наличие ошибок:
open my $fh, '<', $file or die "unable to open '$file' for reading : $!";
и потому use strict
вы должны объявить все переменные. Поэтому ваш скрипт будет выглядеть так:
#!/usr/bin/perl
use strict;
use warnings;
my $pattern = $ARGV[0];
my $file = $ARGV[1];
open $fh, '<', $file or die "unable to open file '$file' for reading : $!";
my @arr = <$fh>;
close $fh; # close as soon as possible
my @lines = grep /$pattern/, @arr;
print @lines;
если ваш файл большой, вы можете избежать чтения его полностью в памяти:
#!/usr/bin/perl
use strict;
use warnings;
my $pattern = qr/$ARGV[0]/;
my $file= $ARGV[1];
print "pattern=$pattern\n";
my @lines;
open my $fh, '<', $file or die "unable to open file '$file' for reading : $!";
while(my $line=<$fh>) {
push @lines, $line if ($line =~ $pattern);
}
close($fh);
print @lines;
как вы уже приняли ответ, я пишу этот ответ Для справки для будущих читателей, ищущих подобные проблемы, но не совсем ваши:
как люди уже ответили, способ моделирования grep с perl заключается в использовании онлайн-подхода. Для использования perl в качестве "лучшего" grep (и найти, и вырезать и...) Рекомендую книгу минимальный perl и вам повезло, потому что глава 'perl как" лучший "grep' является одним из образцов главы.
вот вам еще примеры вдохновил из книги:
perl -wnle '/foo/ and print' null.txt # normal grep
perl -wnle '/foo/ and print "$ARGV: $_"' null.txt # grep -H
perl -wnle '/foo/ and print $ARGV and close ARGV' null_1.txt null_2.txt # grep -l
В последнем примере ARGV-это текущая файловая ручка, и, как и в-l, вы заинтересованы в поиске файлов с совпадением, вы можете распечатать имя файла и перейти к следующему файлу после первого совпадения в файле.
также вы можете искать по абзацу вместо строки:
$ perl -00 -wnl -e '/\bBRIBE\b/i and print;' SenQ.testimony
I knew I'd be in trouble if
I ACCEPTED THE BRIBE!
So I did not.
My minimum bribe is 0k, and she only offered me k,
so to preserve my pricing power, I refused it.
или найти только первый матч:
$ perl -00 -wnl -e '/\bBRIBE\b/i and close ARGV;' SenQ.testimony
I knew I would be in trouble if
I ACCEPTED THE BRIBE!
So I did not.
и, наконец, если вы спросите о grep и Перл, я думаю, что я должен упомянуть ACK. Он реализует в perl функциональность grep и расширяет ее. Это замечательный инструмент, и в качестве плюса вы можете иметь его также как пакет CPAN. Я всегда использую командную строку, я не знаю, можете ли вы получить доступ к ее методам непосредственно из ваших программ perl, но это было бы очень приятно.
вы можете приблизиться к примитивной версии grep
непосредственно в командной строке. The -e
опция позволяет определить скрипт Perl в командной строке. The -n
опция обертывает ваш скрипт примерно так:while (<>){ SCRIPT }
.
perl -ne 'print if /PATTERN/' FILE1 FILE2 ...
немного лучшее приближение grep
будет префиксом имени файла перед каждым напечатанным совпадением. Обратите внимание, что этот пример, как и приведенный выше, не проходит через хлопоты открытия каких-либо файлов. Вместо этого мы используем Perl <>
построить, чтобы перебрать все файлы, и $ARGV
переменная содержит текущее имя файла.
use strict;
use warnings;
my $pattern = shift;
while (my $line = <>){
print $ARGV, ':', $line if $line =~ $pattern;
}