使用Text :: CSV查找带圆括号的文本 - 不起作用

时间:2014-04-24 14:28:06

标签: perl

我有一个csv文件,我正在搜索包含某个模型的行。搜索“2GM”模型时该程序运行良好,但不适用于“2GM(F)”

这是该计划:

#!/usr/bin/perl

# Searches modeltest.txt for all instances of model
# Writes a file called <your model>.txt with all lines 
# in modeltest.txt where the model is found
# Edit $model for different uses
use strict;
use warnings;
use Text::CSV;
my $input_file = 'modeltest.txt';
my @lines = ();
# my $model = '2GM'; # Search for 2GM - WORKS PERFECTLY
my $model = '2GM(F)'; # Search for 2GM(F) - DOES NOT WORK!
# my $model = '2GM\(F\)'; # Does not work either!
print "Search pattern is $model\n";
my $output_file = $model . '.txt';
my $csv = Text::CSV->new({binary => 1, auto_diag => 1, eol=> "\012"})
    or die "Cannot use CSV: ".Text::CSV->error_diag ();

print "Searching modeltest.txt for $model....\n";

open my $infh,  '<', $input_file or die "Can't open   '$input_file':$!" ;
open my $outfh, '>', $output_file or die "Can't open '$output_file':$!" ;

while (my $row = $csv->getline($infh))
{
    my @fields = $csv->fields();
            if (/^($model)$/ ~~ @fields) # search for pattern
            {
            $csv->print ($outfh, ["Y $fields[1]",$model]) or     $csv->error_diag;
            }
}
close $infh;
close $outfh;

$csv->eof or die "Processing of '$input_file' terminated prematurely\n";
print "All Done see output files...\n";

这是modeltest.txt文件:

3,721575-42702,121575-42000,"PUMP ASSY, WATER",,26,COOLING SEA WATER PUMP,-,2GM(F),3GM(F),-,3HM,3HMF,,

1,721575-42702,121575-42000,"PUMP ASSY, WATER",,73,COOLING SEA WATER PUMP,-,2GM,3GM,-,3HM,-,,

45,103854-59191,,"BOLT ASSY, JOINT M12",W,38,FUEL PIPE,1GM,2GM(F),3GM(F),3GMD,3HM,3HMF,,
21,104200-11180,,"RETAINER, SPRING",,11,CYLINDER HEAD,1GM,2GM(F),3GM(F),3GMD,-,-,,
24,23414-080000,,"GASKET, 8X1.0",,77,FUEL PIPE,-,2GM,3GM,-,3HM,-,,
3,124223-42092,124223-42091,IMPELLER,,73,COOLING SEA WATER PUMP,-,2GM,3GM,-,3HM,-,,

以下是2GM.txt的输出

"Y 721575-42702",2GM
"Y 23414-080000",2GM
"Y 124223-42092",2GM

2GM(F)没有输出 - 程序不起作用!我不明白为什么? 任何人都可以对我的问题有所了解吗?

是这个工作再次感谢你!! 很高兴不使用smartmatch ...... 做了以下事情:

将搜索表达式更改为

my $model = "2GM\(F\)";

使用以下代码

while (my $row = $csv->getline($infh))
{
    my @fields = $csv->fields();
            foreach my $field (@fields)
            {
            if ($model eq $field) # search for pattern match in any field
                {
                $csv->print ($outfh, ["Y $fields[1]",$model]) or $csv->error_diag;
                }
            }
}

2 个答案:

答案 0 :(得分:2)

括号在正则表达式中具有特殊含义,它们创建capture groups

如果要在正则表达式中匹配文字括号(或任何其他特殊字符),则需要使用反斜杠对其进行转义,因此搜索模式必须为2GM\(F\)

您还可以使用\Q\E来禁用模式匹配中的特殊字符,并使搜索模式保持不变:

if (/^(\Q$model\E)$/ ~~ @fields) # search for pattern
...

智能匹配运算符~~已被弃用我相信,循环遍历@fields会更直接:

foreach my $field ( $csv->fields() ) {
   if (/^($model)/ =~ $field) # search for pattern
   ...
}

当你可以直接比较时,真的没有理由进行模式匹配:

foreach my $field ( @{$csv->fields()} ) {
   if ($model eq $field) # search for pattern
   ...
}

答案 1 :(得分:1)

  • 最好在正则表达式中使用\Q,以便在定义$model时不必弄乱转义字符。

  • 数据已包含在$row引用的数组中 - 无需再次调用fields来获取数据。

  • 使用List::Util

  • 中的any可以更清晰,速度更快一些
  • use autodie如果你想要做的就是IO错误就死了

  • auto_diag设置为大于1的值会导致它在出现任何错误时死亡,而不仅仅是警告

这是您自己的程序版本,这些问题已经改变

use strict;
use warnings;
use autodie;

use Text::CSV;
use List::Util 'any';

my $input_file  = 'modeltest.txt';
my $model       = '2GM(F)';
my $output_file = "$model.txt";

my $csv = Text::CSV->new({ binary => 1, eol => $/, auto_diag => 2 })
    or die "Cannot use CSV: " . Text::CSV->error_diag;

open my $infh,  '<', $input_file;
open my $outfh, '>', $output_file;

print qq{Searching "$input_file" for "$model"\n};

while (my $row = $csv->getline($infh)) {
  if (any { /\Q$model/ } @$row) {
    $csv->print($outfh, ["Y $row->[1]",$model]);
  }
}

close $outfh;