2015-05-11 46 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(<>)'不。 –