有关Perl正则表达式脚本的建议

时间:2019-05-15 21:50:28

标签: regex perl

我正在尝试编写一个将从文本文件读取的脚本,并将与正则表达式不匹配的行输出到另一个文件。

我有一个两列的文件-第一列是库杜威数字,第二列是条形码。杜威数字应为150 ADD或150.40 ADD。我正在寻找缺少3个字符的作者缩写的行。我的示例文件如下所示:

100.20 SAD 350694345
250 ADD 369803434
300 360349320
300.1534234 ZOO 353000303
210 3633400340

我编写了一个脚本来输出杜威数字后没有作者缩写的所有行。 regex会在可选点之前寻找3位数字,然后是零个或多个可选数字,然后是空格,然后是作者姓名缩写的3个字母。

$filename = 'call.txt';
$output = 'result.txt';
open(FILE, $filename) or die 'Could not open $filename';
foreach $line (<FILE>) {
if ($line !~ /^\d{3}\.*\d* [a-zA-Z]{3}/) {

open (CALL, '>', $output) or die $!;
print CALL $line;
}
}

当我运行脚本时,它仅输出第五行

210 3633400340

我不确定为什么不也选择第3行,因为它与正则表达式不匹配?输出应为所有杜威数字,没有作者的姓名缩写。所以所需的输出是:

300 360349320
210 3633400340

我非常感谢您对此提供的帮助

谢谢 J

2 个答案:

答案 0 :(得分:2)

问题:

  • 您应该始终使用use strict; use warnings qw( all );。 (由于应该始终使用它,因此我们不会在代码段中显示它。)这可以免费检测许多问题。
  • 您不必要使用全局变量。 (use strict;将为您提供帮助,但文件句柄除外。)
  • 通过在循环中重复创建文件,您将破坏除了最后一行输出之外的所有内容。 (这是您要问的问题。)
  • 您的模式错误地将三个以上字符的序列视为三个字符的序列。
  • 通过在列表上下文中使用<>,可以将整个文件逐行加载到内存中,就像将文件逐行读取一样。
  • 您的错误消息不是很有用。

已修复:

#!/usr/bin/perl

use strict;
use warnings qw( all );

my $in_qfn  = 'call.txt';
my $out_qfn = 'result.txt';

open(my $fh_in, '<', $in_qfn)
   or die("Can't open \"$in_qfn\": $!\n");
open(my $fh_out, '>', $out_qfn)
   or die("Can't create \"$out_qfn\": $!\n");

while (<$fh_in>) {
   print $out_fh $_ if !/^\S+\s+\S{3}\s/;
}

如果不对文件名进行编码,该程序将更加有用。

#!/usr/bin/perl

use strict;
use warnings qw( all );

while (<>) {
   print if !/^\S+\s+\S{3}\s/;
}

用法:

script call.txt >result.txt

script <call.txt >result.txt

答案 1 :(得分:0)

每次找到匹配项时,您都会使用截断(“>”)打开文件。将open(CALL,...)移动到for循环之前。