2014-02-09 57 views
2

如果這不是重複的,我會感到驚訝,但我似乎無法找到解決此問題的解決方案。我試圖用另一個字符串替換文件中給定字符串的所有實例。我遇到的問題是腳本打印替換的版本,但保留原文。我很新的perl的,所以我敢肯定,這是一個簡單的問題,我想的東西Perl文件正則表達式不會替換文本

代碼:

my $count; 
my $fname = file_entered_by_user; 
open (my $fhandle, '+<', $fname) or die "Could not open '$fname' for read: $!"; 

for (<$fhandle>) { 
    $count += s/($item_old)/$item_new/g; 
    print $fhandle $_; 
} 
print "Replaced $count occurence(s) of '$item_old' with '$item_new'\n"; 
close $fhandle; 

原始文件:

This is test my test file where 
I test the string perl script with test 
strings. The word test appears alot in this file 
because it is a test file. 

結果文件:

This is test my test file where 
I test the string perl script with test 
strings. The word test appears alot in this file 
because it is a test file 
This is sample my sample file where 
I sample the string perl script with sample 
strings. The word sample appears alot in this file 
because it is a sample file. 

預期的結果的文件:

This is sample my sample file where 
I sample the string perl script with sample 
strings. The word sample appears alot in this file 
because it is a sample file. 

附加信息:

  • $item_old$item_new由用戶提供的。在給出的例子中,我用sample代替test
  • 我對這個問題的單行解決方案不感興趣。它將與更大的程序集成,因此可以從終端運行的單線解決方案不會太有用。

回答

4

問題是,您正在使用+<模式,認爲它會做你認爲它的工作。你正在做的是首先讀取文件中的所有行,將文件句柄位置放在文件末尾,然後打印後面的行。

此行

for (<$fhandle>) { 

讀取文件句柄的所有行,並把它們放在一個列表,在其隨後的循環迭代。它一直讀取到eof,並且只有在此之後您的更改才被添加。

如果您想使您的解決方案正常工作,則必須在打印之前倒帶文件句柄。即

seek($fhandle, 0, 0); 

雖然這些解決方案不是很好,在我看來。尤其是當有內置的功能來處理正是這種事情:

perl -pi.bak -we 's/$item_old/$item_new/g' yourfile.txt 

-i標誌和-p標誌使你的代碼應用到文本文件,並相應地改變它,保存副本的分機號.bak。當然,你必須提供你想要的替代品,因爲你沒有提供它。

編輯:我剛纔看到你不想要一個單行。那麼,爲了做到這一點,你只需要打開正確的文件句柄並將修改過的文件複製到舊的文件中。所以,基本上:

use strict; 
use warnings; 
use File::Copy; 

open my $old, "<", $oldfile or die $!; 
open my $new, ">", $newfile or die $!; 

while (<$old>) { 
    s/$item_old/$item_new/g 
    print $new $_; 
} 
copy $newfile, $oldfile or die $!; 

大部分的時間,使用允許讀取和在同一個文件句柄寫入模式複雜得多,值得注意的是,考慮到它是多麼容易複製工作使用的文件。

+0

謝謝,這解決了我的問題 – JamoBox

+0

不客氣。 – TLP