Perl 模式匹配和替换仅替换第四个单词并保留其他所有内容

Perl 模式匹配和替换仅替换第四个单词并保留其他所有内容

我需要将每一行的第四个单词替换为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

我尝试编写一段代码来执行此操作,但它不起作用,因为它似乎在第一个测试用例中添加了0a 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";
    }
}

答案1

在 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

答案2

一种方法是跳过前 3 个字段,并仅针对电阻器将第 4 个字段替换为 0.0。

$ perl -pe 's/^R(?:\S+\s+){3}\K\S+/0.0/' file
R5_427 MMP15@2:S VDD:1 0.0 TC1=0.0004785156
R5_428 MMP15@2:S lninst_M55:S 0.0

相关内容