在perl中匹配$行的结尾;打印显示与chomp不同的行为

时间:2015-03-04 22:07:15

标签: regex perl

我正在读取一个文件,并在开头跟一个十六进制数的行匹配一个正则表达式,然后是几个点分隔的十六进制值,后跟可选的数组名,它可能包含一个选项索引。例如:

  

010c10 00000000.00000000.0000a000.02300000 myFooArray [0]

while (my $rdLine = <RDHANDLE>) {
  chomp $rdLine;

  if ($rdLine =~ m/^([0-9a-z]+)[ \t]+([0-9.a-z]+)[ \t]*([A-Za-z_0-9]*)\[*[0-9]*\]*$/) {
  ...

包含这些十六进制字符串的源文件也是脚本生成的。这种匹配适用于某些文件,但是当匹配条件中存在最后一个$时,通过完全相同的脚本生成的其他文件(即没有额外的空格,格式等)不匹配。 如果我将条件修改为没有结束$,则行按预期匹配。

另一个奇怪的事情就是调试它,我添加了一个这样的打印语句:

if ($rdLine =~ m/^([0-9a-z]+)[ \t]+/) {
    print "Hey first part matched for $rdLine \n";
}   
if ($rdLine =~ m/^([0-9a-z]+)[ \t]+([0-9.a-z]+)/) {
    print "Hey second part matched for $rdLine \n";
}

以下输入的终端输出会占​​用第一个字符:

  

010000 00000000 foo

   "ey first part matched for 010000                             00000000  foo
    ey second part matched for 010000                             00000000  foo"

如果我删除了chomp,它会正确打印Hey,而不仅仅是ey。

任何线索都赞赏!

2 个答案:

答案 0 :(得分:0)

  

&#34;通过完全相同的脚本生成的其他文件(即没有额外的空格,格式等)在匹配条件中出现最后$时不匹配&#34;

虽然你否认它,但我确信你的文件在行尾之前直接包含一个空格字符。您应该使用Data::Dump进行检查以显示每个文件记录的真实内容。喜欢这个

use Data::Dump;
dd \$read_line;

最好使用

$read_line =~ s/\s+\z//;

取代chomp。这将删除所有空格和制表符,以及每行末尾的回车符和换行符等行尾。

  

&#34;如果我删除了chomp,它会正确打印Hey而不仅仅是ey。&#34;

看起来您正在使用Linux计算机,处理在Windows平台上生成的文件。 Windows使用两个字符CR LF作为记录分隔符,而Linux仅使用LF,因此chomp仅删除尾随LF,而CR会导致字符串的开头被覆盖。

如果您没有追踪空格的次要问题,那么此处的最佳解决方案是将chomp $read_line替换为$read_line =~ s/\R\z//\R character class匹配换行符序列的Unicode概念,并在Perl 5的第10版中引入。但是,前面提到的s/\s+\z//也会处理你的行结尾,应该是你所有的需要。

答案 1 :(得分:0)

鲍罗丁是对的,\ r \ n是罪魁祸首。

我使用了不太优雅的解决方案,但它确实有效:

$rdLine =~ s/\r//g;

接下来是:

chomp $rdLine;