如何使用Perl有条件地用一个单词替换一行?

时间:2010-02-08 10:41:28

标签: perl

我想用'YES'替换以'YES'结尾的行,并用'NO'替换以'NO'结尾的行。我必须申请一个大文件。

输入:

 max. C    13       0.457   0.32   YES
 max. Y    13       0.232   0.33   NO
 max. S     1       0.315   0.87   NO  

输出:

YES
NO
NO

6 个答案:

答案 0 :(得分:3)

虽然保罗的答案是正确的,但我想指出还有另一种方法来看待你的问题。您的问题表明该行以“是”或“否”结束。因此,你可以做的另一件事是分割线并打印最后一个元素,如果它匹配“是”或“否”:

perl -lape'$_=$F[-1] if $F[-1]=~m/^(?:YES|NO)$/'

在您的示例中,所有行都以YES或NO结尾。如果输入中的所有行都是如此,则可以简化为:

perl -lape'$_=$F[-1]'

使用Perl命令行标志的简短说明(您也可以在“perldoc perlrun”中阅读):

  • -l用于自动选择输入字符串并在打印时附加“\ n”。
  • -a自动将空格上的输入行拆分为@F数组,与“-n”或“-p”一起使用。
  • -p创建一个在给定输入文件的行上运行的循环,并在代码运行后在末尾执行“打印”。
  • -e当然是在命令行上提供代码的标志

所以基本上命令行标志完成了大部分工作。我唯一需要做的就是将$ F [-1](行的最后一个元素)分配到$ _,这是因为“-p”而打印的东西。

我的目标不是玩Perl Golf并向您展示一个回答问题的简短方法,而是我试图指出从一个稍微不同的角度思考一个问题可以向您展示解决它的不同方法,这可能更好/更优雅。因此,请不要关注哪个解决方案更短,而是考虑不同的人如何从不同的方向攻击这个简单的问题,以及如何做到这一点。

还有一点,你写了“我想替换一行”。如果你想在输入文件中替换,那么“-i”(就地替换)命令行标志就是你的朋友:

perl -lapi.bak -e'$_=$F[-1]'

答案 1 :(得分:2)

列表上下文匹配返回捕获的子串:

#!/usr/bin/perl

use strict; use warnings;

while ( <DATA> ) {
    if (my ($resp) = /(YES|NO)\s+\z/) {
        print "$resp\n";
    }
}

__DATA__
 max. C    13       0.457   0.32   YES
 max. Y    13       0.232   0.33   NO
 max. S     1       0.315   0.87   NO

而且,如果您只想捕获'Y''N',则有两种选择。一种是使用两个捕获缓冲区并使用grep来填充不匹配的子字符串:

if (my ($resp) = grep defined, /(?:(Y)ES)|(?:(N)O)\s+\z/ ) {
    print "$resp\n";
}

或者,更好的是,使用命名的捕获缓冲区:

if ( /(?: (?<resp>Y) ES) | (?: (?<resp>N) O) \s+\z/x ) {
    print "$+{resp}\n";
}

输出:

Y
N
N

答案 2 :(得分:1)

perl -p -e 's/.*(YES|NO)\s*$/$1/;' 

如果您想要Y和N而不是YES而NO,则将其更改为

s/.*(Y|N)[ESO]+$/$1/;

要阅读有关perl正则表达式,子目录等的更多信息,请从安装了perl的系统命令行中查看“perldoc perlre”

答案 3 :(得分:1)

如果你需要,这取决于你。

awk '{print $NF}' file_name

答案 4 :(得分:1)

您也可以使用以下代码,

use strict;
use warnings;
my $var;
open (FH,"<file") or die "$! can't open";
while($var=<FH>)
{
     chomp($var);
     $var=~s/.*(YES|NO)$/$1/;
     print "$var\n";
}

在这段代码中我使用了chomp函数。此函数用于删除“\ n”。之后我检查了行的结尾包含“是”或“否”

答案 5 :(得分:0)

许多发布的答案使用替换s///来更改该行的值。 虽然这确实有效,但维护起来并不容易。那么为什么不在成功匹配后将字符串设置为 YES NO

use strict;
use warnings;
use autodie;

my $filename = 'file'

{
  open my $fh, '<', $filename;
  while( my $line = <$fh> ){
     chomp($line);

     if( $line =~ /(YES|NO)$/ ){
       $line = $1;
     }

     print $line, "\n";
  }
  close $fh;
}