2012-07-16 52 views
2

好吧,我想刪除第一次出現的字符串,比方說,「狗」,在文件中,只有第一次出現。所以如果文件如下:Perl刪除第一次發生

這條狗很高興。
狗喜歡跑。

輸出將

的很高興。
狗喜歡跑。

我有以下代碼:

#!/usr/local/bin/perl 

use warnings; 
use strict; 

my $file = $ARGV[0]; 
my $out = $ARGV[1]; 

open (IN, "<$file"); 
open (OUT, ">$out"); 
while(<IN>){ 
    s/dog/ /; 
    print OUT $_; 
} 

close IN; 
close OUT; 

而且它的工作原理,但不是repacing只是一審,它替代了單詞的所有實例。我以爲我不得不使用全局修飾符g來替換所有實例?爲什麼它會替換我正在搜索的字符串的所有實例?這可能是一些簡單的錯誤,我沒有看到。

回答

7

它會在每次評估操作符時替換第一個實例,並且爲每一行評估操作符,因此可以替換每行中的第一個實例。如果您使用了/g,那麼您將一直在替換每行中的所有實例。

my $seen; 
while (<>) { 
    ++$seen if !$seen && s/dog//; 
    print; 
} 

或者作爲一個班輪:

perl -pe'++$seen if !$seen && s/dog//;' infile >outfile 

您可以添加文件句柄回來,但上述接受更標準,更靈活的使用。要獲得與您的代碼相同的效果,你只需要使用

script.pl infile >outfile 

,而不是

script.pl infile outfile 
+0

@eckes,是啊,我注意到誤讀的問題,並固定它在一分鐘前。 – ikegami 2012-07-16 14:47:13

+0

偉大的工作。但要澄清,infile> outfile與infile outfile有什麼不同? – user1440061 2012-07-16 15:22:26

+0

如果您使用'script.pl infile outfile',我的代碼會將'infile'和'outfile'視爲輸入文件。 – ikegami 2012-07-16 15:25:45

3

這可以用一行代碼來實現:

perl -0777 -pe 's/dog/ /' inputfile > outputfile 

-0777開關會將文件讀取爲一行,這將使您的替換工作按預期工作。這一個班輪相當於程序文件:

$/ = undef; 
$\ = undef; 
while (<>) { 
    s/dog/ /; 
    print; 
} 
2
while (<>) { 
    my $found = s/dog//; 
    print; 
    last if $found; 
} 
print while <>;