簡體   English   中英

使用perl修改文件中的字符串

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM