Regular-Expression

Perl 模式匹配和替換以僅替換第 4 個單詞並保留其他所有內容

  • November 2, 2020

我需要將每行的第 4 個單詞替換為0

原來的:

R5_427 MMP15@2:S VDD:1 967.796 TC1=0.0004785156
R5_428 MMP15@2:S lninst_M55:S 0.001

預期輸出:

R5_427 MMP15@2:S VDD:1 0 TC1=0.0004785156
R5_428 MMP15@2:S lninst_M55:S 0

我試圖編寫一段程式碼來做到這一點,但它不起作用,因為它似乎添加了 a0以及967.796在第一個測試案例中。我正在尋找一個通用的解決方案,而不是依賴於第三個單詞之後的確切單詞數。

我的嘗試:

while(<RD>)
{
   my $line;
   $line = $_;
   chop $line; 
   if ($line =~ /^R(\S+)\s+(\S+)\s+(\S+)\s+(.*$)/) {
       my $mod_line = "R$1 $2 $3 0 $4";
       print WR "$mod_line\n";
   }
   else {
       print WR "$line\n";
   }
}

在 Perl 中,你可以這樣做:

#!/usr/bin/env perl

while (<>) {
 ## split the line into fileds on whitespace
 my @fields = split(/\s+/);
 ## set the 4th field (numbering starts at 0) to "0" if
 ## this line starts with an R (since that's what you had originally)
 $fields[3] = 0 if /^R/;
 ## join thew fields with a space and print
 print join(" ", @fields) . "\n";
}

如果你在你的例子上執行上面的,你會得到:

$ foo.pl file 
R5_427 MMP15@2:S VDD:1 0 TC1=0.0004785156
R5_428 MMP15@2:S lninst_M55:S 0

或者,如果您想使用更複雜的正則表達式保留原始邏輯,您可以這樣做:

#!/usr/bin/env perl
open(my $RD, '<', $ARGV[0]);
while(<$RD>)
{
 ## you want chomp, not chop. chomp only removes trailing newlines
 ## while chop removes the last character no matter what it is.
 ## You also don't need the $line variable, perl will default to $_
 chomp;
 ## You don't need to capture every group, only the
 ## ones you will use later. Also, to allow for only
 ## three fields, you need '\s*.*' and not '\s+.*'
 if (/^(R\S+\s+\S+\s+\S+)\s+\S+(\s*.*)/) {
   ## No need for a temp variable, just print
   print "$1 0 $2\n";
 }
 else {
   print "$_\n";
 }
}

當然,你真的不需要為此編寫腳本,你可以只寫一個單行:

$ perl -lane '$F[3] = 0 if /^R/; print join(" ", @F)' file 
R5_427 MMP15@2:S VDD:1 0 TC1=0.0004785156
R5_428 MMP15@2:S lninst_M55:S 0

引用自:https://unix.stackexchange.com/questions/617437