我有一个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;
}
}
}
答案 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
来获取数据。
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;