Как я могу быстро найти первую строку файла, которая соответствует регулярному выражению?

Я хочу найти строку в файле, используя регулярные выражения, внутри скрипта Perl.

Предполагая, что это в системе с установленным grep, лучше:

  • вызвать внешний grepчерез open()команду
  • open()файл напрямую и использовать whileцикл и if ($line =~ m/regex/)?
13.12.2008 14:30:36
7 ОТВЕТОВ

В современной реализации Perl код регулярного выражения должен быть таким же быстрым, как и в grep, но если вы беспокоитесь о производительности, почему бы вам просто не попробовать его? С точки зрения чистоты кода и надежности, вызов внешнего инструмента командной строки определенно не годится.

9
13.12.2008 14:53:11

Это зависит.

  • работа внутри Perl экономит ваше время запуска процесса и другие связанные с этим затраты ресурсов.
  • grep, вероятно, быстрее, чем выполняет ту же работу в Perl, но не так сильно.

Я бы сказал, делать это в Perl, если производительность не заставляет вас оптимизировать.

3
13.12.2008 14:53:46

С grep нужно быть осторожным: если в последних дистрибутивах Linux переменная среды LANG определяет тип UTF-8 (например, у меня LANG = en_GB.UTF-8), то grep, sed, sort и, возможно, куча другого текста. -процессные утилиты работают примерно в 10 раз медленнее. Так что следите за этим, если вы проводите сравнение производительности. Теперь я называю свою команду grep:

LANG= LANGUAGE= /bin/grep

Изменить: На самом деле, это больше похоже на 100 раз медленнее

5
31.08.2009 22:40:24

Вам не нужно openявно файл

my $regex = qr/blah/;
while (<>) {
  if (/$regex/) {
    print;
    exit;
  }
}
print "Not found\n";

Поскольку вы, похоже, обеспокоены производительностью, я позволю сопоставить и printиспользовать значение по умолчанию $_, не назначая <>что-либо, что немного быстрее. В нормальном производственном коде

while (my $line = <>) {
  if ($line =~ /$regex/) {
    print $line;
    exit;
  }
}

будет предпочтительным.

Изменить: Предполагается, что файл для проверки дается в командной строке, что, как я только что заметил, вы не указали, применяется в вашем случае.

6
13.12.2008 16:43:19
Это немного быстрее, но использование самого глобального $ _ не стоит 10% (измеряется поиском / zebra / в строке 240k / usr / dict / words). Если вы выделите $ line вне цикла while, снижение производительности исчезнет.
Schwern 13.12.2008 22:01:05

Это зависит. Если вы хотите оптимизировать время разработки,

$line = `grep '$regex' file | head -n 1`;

это явно то, что нужно сделать.

Но это происходит за счет необходимости запуска внешних процессов, в зависимости от того, что установлено помимо perl, и потери возможности делать подробные отчеты об ошибках, когда что-то идет не так.

3
14.12.2008 06:50:07
Вместо этого используйте встроенный grep, --max-count=1чтобы остановить поиск в первом совпадении. Таким образом вы избегаете накладных расходов на обработку файла до конца (что может быть важно для больших файлов), а также накладных расходов на запуск другого процесса для запуска head -n 1.
Nathan S. Watson-Haigh 10.10.2012 22:47:29
это расширение GNU. полезно, но не обязательно всегда присутствует
ysth 11.10.2012 04:45:39

Однажды я написал скрипт для поиска регулярных выражений в больших текстовых файлах (около 10 МБ каждый). Я сделал это с помощью регулярных выражений Perl и заметил, что все идет довольно медленно. Поэтому я попытался запустить grep из скрипта, и повышение скорости было довольно значительным. Итак, по моему опыту, встроенные в Perl регулярные выражения работают медленнее, чем grep. Но вы, вероятно, заметите это только с большими файлами. Мой совет: попробуйте оба пути, и посмотрите, как это происходит.

1
15.12.2008 20:33:40
sed '/pattern/q' file
2
1.04.2010 17:12:02