Замена Perl регулярным выражением - PullRequest
0 голосов
/ 21 января 2012

Когда я запускаю эту команду через Perl one liner, она выбирает регулярное выражение - так что это не может быть плохо.

more tagcommands | perl -nle 'print /(\d{8}_\d{9})/' | sort 

12012011_000005769
12012011_000005772
12162011_000005792
12162011_000005792

Но когда я запускаю этот скрипт поверх вызова команды ниже, это не подобрать регулярное выражение.

#!/usr/bin/perl
use strict; 
my $switch="12012011_000005777";
open (FILE, "more /home/shortcasper/work/tagcommands|");
my @array_old = (<FILE>) ;
my @array_new = @array_old ;
foreach my $line(@array_new) {
        $line =~ s/\d{8}_\d{9}/$switch/g;
        print $line;
        sleep 1;
}

Это данные, которые я передаю в скрипт

/CASPERBOT/START URL=simplefile:///data/tag/squirrels/squirrels    /12012011_000005777N.dart.gz CASPER=SeqRashMessage
/CASPERBOT/ADDSERVER simplefile:///data/tag/squirrels/12012011_0000057770.dart.trans.gz
/CASPERRIP/newApp multistitch CASPER_BIN
/CASPER_BIN/START URLS=simplefile:///data/tag/squirrels    /12012011_000005777R.rash.gz?exitOnEOF=false;binaryfile:///data/tag/squirrels/12162011_000005792D.binaryBlob.gz?exitOnEOF=false;simplefile:///data/tag/squirrels/12012011_000005777E.bean.trans.gz?exitOnEOF=false EXTRACTORS=rash;island;rash BINARY=T

Ответы [ 2 ]

4 голосов
/ 21 января 2012

Вы должны изучить свой однострочник, чтобы увидеть, как он работает.Сначала проверьте perl -h, чтобы узнать об используемых переключателях:

-l[octal]         enable line ending processing, specifies line terminator
-n                assume "while (<>) { ... }" loop around program

Первый не совсем понятен, но на самом деле -l означает chomp каждую строку, а затем измените $\ и $/ до новой строки.Итак, ваш однострочный:

perl -nle 'print /(\d{8}_\d{9})/'

На самом деле это делает:

$\ = "\n";
while (<>) {
    chomp;
    print /(\d{8}_\d{9})/;
}

Очень простой способ убедиться в этом - использовать команду Deparse:

$ perl -MO=Deparse -nle 'print /(\d{8}_\d{9})/'
BEGIN { $/ = "\n"; $\ = "\n"; }
LINE: while (defined($_ = <ARGV>)) {
    chomp $_;
    print /(\d{8}_\d{9})/;
}
-e syntax OK

Итак, вот как вы преобразуете это в рабочий скрипт.

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

use strict; 
my $switch="12012011_000005777";
open (FILE, "more /home/shortcasper/work/tagcommands|");
my @array_old = (<FILE>) ;
my @array_new = @array_old ;
foreach my $line(@array_new) {
        $line =~ s/\d{8}_\d{9}/$switch/g;
        print $line;
        sleep 1;
}

Прежде всего, почему вы открываететруба из команды more для чтения текстового файла?Это все равно что вызывать эвакуатор за такси.Просто откройте файл.Или еще лучше, не надо.Просто используйте оператор diamond, как вы делали это в первый раз.

Вам не нужно сначала копировать строки файла в массив, а затем использовать массив.while(<FILE>) - это простой способ сделать это.

В одной строке вы печатаете регулярное выражение.Ну, вы печатаете возвращаемое значение регулярного выражения.В этом сценарии вы печатаете $line.Я не уверен, как ты думал, что это сделает то же самое.

Ваше регулярное выражение здесь удалит весь набор чисел и заменит его на те, что указаны в вашем скрипте.Ничего другого.

Вы также можете знать, что sleep 1 не будет делать то, что вы думаете.Попробуйте этот однострочный, например:

perl -we 'for (1 .. 10) { print "line $_\n"; sleep 1; }'

Как вы заметите, он просто подождет 10 секунд, а затем напечатает все сразу.Это связано с тем, что по умолчанию perl печатает в стандартный выходной буфер (в оболочке!), И этот буфер не печатается до тех пор, пока не будет заполнен или сброшен (после завершения выполнения perl).Итак, это проблема восприятия.Все работает так, как должно, вы просто этого не видите.

Если вы абсолютно хотите, чтобы в вашем скрипте содержалось утверждение сна, вы, вероятно, захотите autoflush , например STDOUT->autoflush(1);

Однако, почему вы это делаете?Так у вас будет время прочитать цифры?Если это так, поместите этот оператор more в end вашего однострочного текста вместо:

perl ...... | more

, который перенаправит вывод в команду more, так что вы можете прочитатьэто в вашем собственном темпе.Теперь для вашего однострочного текста:

Всегда также используйте -w, если только вы не хотите специально избегать получения предупреждений (чего, в принципе, никогда не следует).

Ваш однострочник будет печатать толькопервый матчЕсли вы хотите напечатать все совпадения в новой строке:

perl -wnle 'print for /(\d{8}_\d{9})/g'

Если вы хотите напечатать все совпадения, но оставьте те из одной строки в одной строке:

perl -wnle 'print "@a" if @a = /(\d{8}_\d{9})/g'

Ну, это должно покрыть это.

1 голос
/ 21 января 2012

Ваш open вызов может быть неудачным (вы всегда должны проверять результат open, чтобы убедиться, что он успешен, если от этого зависит остальная часть программы), но я считаю, что ваша проблема заключается в усложнении, открывая pipe из команды more вместо простого открытия самого файла. Измените открытие на просто

open FILE, "/home/shortcasper/work/tagcommands" or die $!;

и все должно улучшиться.

...