【问题标题】:How can I search a particular column in Perl?如何在 Perl 中搜索特定列?
【发布时间】:2008-11-04 05:28:52
【问题描述】:

我有一个包含一些数据的文本文件。我正在尝试在 ID 列中搜索 EA 并打印整行。但代码识别所有 EA 并打印所有行。我应该添加什么代码来满足条件?再次感谢:-)!

数据:
姓名 年龄 ID
---------------------
克里斯特,22,EA2008
JEAN,21,ES4567
JAK,45,EA2008

代码打印:
克里斯特,22,EA2008
JEAN,21,ES4567
JAK,45,EA2008

期望的输出:
KRIS,22,EA2008
凯恩,45 岁,EA2008,

file='save.txt';
open(F,$file)||die("Could not open $file");
while ($line=<F>){
if ($line=~ m/$EA/i) {
my @cells=($f1,$f2,$f3)= split ',',$line;
print "<TD>f1</TD>";
print "<TD>f2</TD>";
print "<TD>f3</TD>";
}

【问题讨论】:

    标签: perl search csv


    【解决方案1】:

    brian 和 Jeremy 的代码组合解决了所有问题:

    use strict;
    use warnings;
    
    my $file = 'save.txt';
    open my $fh, "<", $file or die "Could not open $file: $!";
    
    while ($line = <$fh>)
    {
        my($f1, $f2, $f3) = split ',', $line;
        if ($f3 =~ m/EA/i)
        {
            print "<TD>$f1</TD>";
            print "<TD>$f2</TD>";
            print "<TD>$f3</TD>";
        }
    }
    

    Brian 用 use CGI;my $EA = param('keyword'); 概括了匹配模式,但我取消了它,因为我认为它不适用于该问题。

    【讨论】:

    • 参数内容来自 OPs cmets 到其他答案。
    • 好的——够公平的。我设法错过了。无论如何,这就是为什么您要接受代码审查的原因。 :-D
    【解决方案2】:

    您应该发布您用来说明问题的实际示例程序。这是你的清理程序:

    use strict;
    use warnings;
    
    use CGI;
    
    my $EA = param('keyword');
    
    my $file = 'save.txt';
    open my $fh, "<", $file or die "Could not open $file: $!";
    
    while( $line=<$fh> ) {
       if( $line=~ m/$EA/i ) {
           my( $f1, $f2, $f3 ) = split ',', $line;
           print "<TD>$f1</TD>";
           print "<TD>$f2</TD>";
           print "<TD>$f3</TD>";
           }
       }
    

    这里有一些可以帮助你的事情。

    • 您的变量需要它们的印记。没有他们,他们什么也做不了。
    • 当您尝试打开文件并想报告错误时,请包含 $!变量,以便您查看错误是什么。
    • 您可以直接拆分为标量变量。这只是一个列表作业。您不需要额外的 @cell 变量。
    • 通过使用一些空格来给你的陈述一些喘息的空间。毕竟它是免费的。

    【讨论】:

    • 你的清理程序很好 - 只是它不能解决问题。
    • 我没有说它解决了问题。我什至都懒得去想这个问题。我解决了这个问题:)
    【解决方案3】:

    你几乎成功了,我认为这应该可行:

    file='save.txt';
    open(F,$file)||die("Could not open $file");
    
    while ($line=<F>){
      my @cells=($f1,$f2,$f3)= split ',',$line;
      if ($f3=~ m/$EA/i) {
        print "<TD>f1</TD>";
        print "<TD>f2</TD>";
        print "<TD>f3</TD>";
      }
    }
    

    这会将行拆分为列首先,然后仅在第三列上执行正则表达式。

    顺便说一句,您的代码可能还有其他问题(例如,那些打印语句看起来不像打印变量的值)但我不太了解 perl,所以我只回答了您的主要问题...

    【讨论】:

    • 我的 $EA=param('keyword');//example:$EA= 'EA'
    • 您已经正确解决了核心问题 - 拆分然后匹配 - 但没有修复 bust 语法。 Brian 修复了 bust 语法 - 但没有解决核心问题。
    【解决方案4】:

    与其尝试自己进行 CSV 解析,不如使用出色而高效的Text::CSV_XS。这将处理转义和引用。

    #!/usr/bin/perl -w
    
    use Text::CSV_XS;
    
    my $csv = Text::CSV_XS->new();
    
    # Skip to the data.
    while(<DATA>) {
        last if /^-{10,}$/;
    }
    
    while( my $row = $csv->getline(*DATA) ) {
        print "@$row\n" if $row->[2] =~ /EA/;
    }
    
    
    __DATA__
    Name Age ID
    ---------------------
    KRISTE,22,EA2008
    J**EA**N,21,ES4567
    JAK,45,EA2008
    

    【讨论】:

      【解决方案5】:

      或者,您可以更改您的正则表达式以匹配列表中的第三项:

      /[^,]*,[^,]*,.*EA/
      

      【讨论】:

      • [^,]* 会比 .*? 更好,因为它明确指出您只需要非逗号字符,这使您的意图对人类读者更加明显,并允许正则表达式引擎避免(可能很耗时)回溯。
      • @Dave Sherohman,同意(主要是关于回溯——我觉得它不再可读)。答案已编辑。
      【解决方案6】:

      您的正则表达式不适合您尝试执行的操作。 Ben 的解决方案有效,尽管开头也应该有一个 ^,这确保了正则表达式将从字符串的开头开始匹配:

      /^.?,.?,.*EA/

      另外,从 perl 的角度来看,您的代码有点嘈杂。如果你想让你的代码更容易阅读,你可以这样做(我使用的是 Ben 的正则表达式):

      $f = 'save.txt';

      打开(F,$文件);

      @matches = grep { /^.?,.?,.*EA/ } ;

      现在@matches 将保存你所有匹配的记录,你可以用它们做你想做的事。

      【讨论】:

        猜你喜欢
        • 2018-12-10
        • 2013-10-27
        • 2016-04-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-06-02
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多