[英]Modify a string in a file with perl
我有一個文件d00.dat,我需要將字符串d01更改為d02 ...使用以下代碼,它將在控制台中打印修改內容,但它們在文件d00.dat中沒有更改...我該如何更改去做?
my $line = 0;
my $filename = "d00.dat";
open(my $fh, '<', $filename) || die "file could not open $! \n";
while( $line = <$fh>) {
if( $line =~ s/d01/d02/g ){
print "$line\n";
}
最簡單,最快的解決方案是將文件讀入內存,進行更改,然后將更改寫回到文件中。
my $qfn = "d00.dat";
my $file;
{
open(my $fh, '<', $qfn)
or die("Can't open \"$qfn\": $!\n");
local $/;
$file = <$fh>;
}
$file =~ s/d01/d02/g;
{
open(my $fh, '>', $qfn)
or die("Can't create \"$qfn\": $!\n");
print($fh $file);
}
作為單線:
perl -i -pe's/d01/d02/g' d00.dat
如果您只想更改這些位置,則不必-不得不替換整個文件。 †
您可以將包括更改在內的每一行打印到另一個文件,然后將其復制。 許多工具都以這種方式工作。 或者,您可以讀取所有行,對其進行適當更改,然后覆蓋文件。
my $filename = "d00.dat";
open(my $fh, '<', $filename) || die "file could not open $! \n";
my @new_lines = map { s/d01/d02/g; $_ } <$fh>;
close $fh;
open(my $fh_out, '>', $filename) || die "file could not open $! \n";
print $fh_out $_ for @new_lines;
close $fh_out;
由於open
將關閉文件句柄(如果已打開),您也可以執行
open my $fh, '<', $filename or die "Can't open $filename: $!";
my @new_lines = map { s/d01/d02/gr } <$fh>;
open $fh, '>', $filename or die "Can't open $filename: $!";
print $fh $_ for @new_lines;
close $fh;
我在其中刪除parens並將其更改為or
,然后將$filename
添加到錯誤消息中。 我還在正則表達式中使用了/r
修飾符(“ 非破壞性替換 ”),通過它返回更改后的字符串-正是該map
所需的字符串,因此現在我們不需要在末尾使用單獨的$_
塊。
問題中出現的die
消息末尾的換行符有一個微妙的結果:它抑制了有關發出die
的行號的信息。 雖然這有時期望,在大多數情況下,它是不是在這里我們當然希望看到調用,它失敗的行號! 因此,我在die
的消息中刪除了該額外的換行符。
†文件是字節序列。 因此,如果我們想用yes
代替一個nope
...當我們替換了前三個字符時,最后一個字符e
會發生什么? 我們必須按照原始的nope
移動文件的其余部分,以覆蓋e
,因此現在遵循yes
。 因此,我們需要覆蓋文件的其余部分,實際上,僅替換整個文件要容易得多。
如果我們想用yeah
代替nope
...好吧,現在是4比4,實際上我們可以覆蓋這4個字符。 但是,這種情況很少發生,並且執行起來更加復雜。
當問題要求用d02
替換d01
,我想這是一個示例,而實際上字符串的長度通常不相同。 即使他們正在...替換文件也更加容易和安全,並且很可能不會發現效率損失。
Perl有一個開關可以就地修改文件。 我認為這就是您要尋找的:
perl -i.bak -p -e 's/d01/d02/g;' d00.dat
這將
d00.dat
重命名為d00.dat.bak
d00.dat.bak
d02
替換每次出現的d01
d00.dat
說明:
-i
就地編輯文件,如果給定了一些后綴,則可以選擇進行備份。 例如, -i.bak
將創建$file.bak
, -i.before
將創建$file.before
等。如果沒有后綴(僅-i
),將沒有備份,因此請考慮這樣做是危險的。
-p
放置像
while(<>) { # your code print; }
在這種情況下( s/…/…/g;
)
-e
僅僅表示“執行以下語句” 。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.