2015-05-11 22 views
2

可能是一个非常简单的问题: 我有一个perl文件sed.perl,它将一个字符串作为输入,在那里进行一些替换并将其输出到标准输出中。如何在终端管道中运行perl文件

#!/usr/bin/perl 
use warnings; 
use strict; 
use diagnostics; 
use feature 'say'; 
#use Cwd; 

my ($text) = @ARGV; 

$text =~ s/\.\)\n/'\.'\)\n/; 

print $text; 

我想从终端管道输出字符串喂脚本。让我们这样说:

cat input.txt | perl sed.perl 

但这不起作用:Use of uninitialized value $text in substitution (s///) at

使用分数符号不工作之一:

cat input.txt | perl sed.perl - 

回答

0

你试图阅读文本就好像它是一个参数一样,但事实上,在管道中,来自input.txt的信息将从stdin中读取。用流水线stdout从左边的流程连接到stdin的正确流程。

2

@ARGV不会做你认为的事情。这实际上是传递给perl的参数。

E.g. :

myscript.pl some arg 

@ARGV将举办'some', 'arg'

你想要的是STDIN文件句柄。

例如

#!/usr/bin/perl 
use strict; 
use warnings; 

while (<STDIN>) { 
    s/something/somethingelse/g; 
    print; 
} 

现在,这是什么东西做的是阅读STDIN一行一行。你的模式包括\n。你真的需要它吗?它看起来像你“只是”使用它作为一个线锚,所以你可以使用:

s/\.\)$/'\.'\)/g; 

$是“行结束”正则表达式 - 见perlre更多。

然而,在由reinierpost的评论中指出 - 有另一件事可能是有用的了解 - Perl有“钻石经营者” <>它做了两两件事:如果文件名被指定为脚本

  • ,打开他们并从他们那里读取。
  • 如果没有指定参数,读取STDIN

所以,你可以这样做:

while (<>) { 
    s/something/somethingelse/g; 
    print; 
} 

然后你的脚本可以通过调用:

cat input.txt | ./yourscript.pl 

或者:

./yourscript.pl input.txt 

而且你将有相同的结果。

+2

你想补充一点,它的更好风格使用'<>'而不是'':脚本的用户可以通过'<>''''作为参数传递输入来自的文件的名称,这对于Unix实用程序来说是一种常见而有用的约定跟随。 – reinierpost

+0

好点 - 修改后。 – Sobrique

+0

'\ n'会匹配(除非您使用-l与-n或-p) – ysth

0

正如其他人所提到的,@ARGV包含您的脚本的参数,您将需要使用STDIN来代替。

最短的解决方案似乎是:

#/usr/bin/env perl 

use strict; 

while(<>) { 
    print s/\.\)$/'.')/r; 
} 

请注意,你也可以使用一个班轮如下实现你的例子的结果:

cat input.txt | perl -pe 's/your/substitution/' 
+0

你不需要在模式的末尾使用'g'吗? – Sobrique

+1

不,因为OP想在行尾匹配,所以不需要g或者 – ysth

+0

btw,'for(<>)'将_whole_文件加载到内存中,而while(<>)'不。 –