当我在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
答案 0 :(得分:4)
你应该研究你的单行,看它是如何运作的。首先检查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})/;
}
实际上这样做:
$ 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
一种非常简单的方法是使用Deparse命令:
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
首先,为什么要从while(<FILE>)
命令打开管道来读取文本文件?这就像叫一辆拖车去取你的出租车。只需打开文件即可。或者更好,不要。只需使用钻石操作符,就像你第一次做的那样。
您无需先将文件行复制到数组中,然后再使用该数组。 $line
是一种简单的方法。
在你的单行中,你打印正则表达式。好吧,你打印正则表达式的返回值。在此脚本中,您打印sleep 1
。我不确定你认为那会做同样的事情。
此处的正则表达式将删除所有数字集,并将其替换为脚本中的数字。没别了。
您可能也知道perl -we 'for (1 .. 10) { print "line $_\n"; sleep 1; }'
不符合您的想法。试试这个单行,例如:
STDOUT->autoflush(1);
正如您将注意到的,它只需等待10秒钟,然后立即打印所有内容。这是因为perl默认打印到标准输出缓冲区(在shell中!),并且该缓冲区在完全或刷新之前不打印(当perl执行结束时)。所以,这是一个感知问题。一切都像它应该的那样,你只是看不到它。
如果您绝对想在脚本中使用sleep语句,则可能需要autoflush,例如more
但是,你为什么这样做?难道你有时间阅读这些数字吗?如果是这样,请将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}}
嗯,这应该涵盖它。
答案 1 :(得分:1)
你的open
电话可能会失败(如果程序的其余部分依赖它,你应该总是检查open
的结果以确保它成功)但我相信你的问题很复杂通过从more
命令打开管道而不是简单地打开文件本身。将打开更改为
open FILE, "/home/shortcasper/work/tagcommands" or die $!;
事情应该有所改善。