Perl匹配仅返回“1”。布尔?为什么?

时间:2011-10-21 21:45:45

标签: regex perl parsing

这一点必须明显,但我只是没有看到它。

我有一份包含数千条记录的文件,如下所示:

Row:1 DATA:
[0]37755442
[1]DDG00000010
[2]FALLS
[3]IMAGE
[4]Defect
[5]3
[6]CLOSED

我设法将每条记录分开,我现在正试图解析每个字段。

我正在尝试匹配编号的标题,以便我可以提取成功的数据,但问题是我的匹配仅在成功时返回“1”而如果不成功则返回任何内容。我尝试申请的任何比赛都会发生这种情况。

例如,应用于每个记录中的简单单词:

my($foo) = $record=~ /Defect/;
print STDOUT $foo;
如果每个记录包含“缺陷”,则

打印出“1”,如果包含其他内容则不打印出任何记录。

可替换地:

$record =~ /Defect/;
print STDOUT $1;

绝对不打印。

$record =~ s/Defect/Blefect/
另一方面,

将“Blefect”替换为“Blefect”完美无缺。

我真的很困惑为什么我的比赛的回报如此棘手。 任何帮助将不胜感激。

6 个答案:

答案 0 :(得分:17)

您需要使用捕获括号来实际捕获:

if ($record =~ /(Defect)/ ) {
    print "$1\n";
}

答案 1 :(得分:7)

我认为你真正想要的是将正则表达式括在括号中:

my($foo) = $record=~ /(Defect)/;

在列表上下文中,返回组,而不是匹配本身。并且您的原始代码没有组。

答案 2 :(得分:4)

=~ perl运算符接受一个字符串(左操作数)和一个正则表达式(右操作数),并将字符串与RE匹配,返回一个布尔值(true或false),具体取决于重新匹配。

现在perl并没有真正的布尔类型 - 相反,每个值(任何类型)都被视为' true'或者' false'在布尔上下文中 - 大多数事情是真实的,但是空字符串和特殊的' undef'未定义的东西的值是假的。因此,当返回布尔值时,它通常使用' 1'对于真实和'' (空字符串)表示错误。

至于你的上一个问题,试图打印$1的地方什么都没打印。每当您匹配正则表达式时,perl会将$1$2 ...设置为带有RE的带括号的子表达式的值。但是在您的示例中,没有带括号的子表达式,因此$ 1始终为空。如果将其更改为

$record =~ /(Defect)/;
print STDOUT $1;

你会得到更符合你期望的东西(Defect如果它匹配则没有,如果它不匹配则没有。

我通常看到的regexp匹配最常见的习惯是:

if ($string =~ /regexp with () subexpressions/) {
    ... code that uses $1 etc for the subexpressions matched
} else {
    ... code for when the expression doesn't match at all
}

答案 3 :(得分:2)

来自perlop, Quote and Quote-Like operators [我添加的括号中的位]:

  

/ PATTERN / msixpodualgc

     

在字符串中搜索模式匹配,标量上下文中的如果成功则返回true [1],如果失败则返回false [undef]。

(查看s///部分也很有用; - )

Perl只是没有谨慎的布尔类型或true / false别名,因此经常使用1undef:但是,它可以很好地可以是其他值而不会使文档不正确。

永远不会定义

$1,因为没有捕获组:可能需要$& (aka $MATCH)吗? (或者更好的是,将正则表达式更改为具有捕获组; - )

快乐的编码。

答案 4 :(得分:1)

my($foo) = $record=~ /Defect/;
print STDOUT $foo;

而不是这样你应该做

$record =~ /Defect/;
my $foo = $&; # Matched portion of the $record.

因为你的目标似乎是获得匹配的部分。 返回值为true / false,表示匹配是否成功。

您可能会发现http://perldoc.perl.org/perlreref.html方便。

答案 5 :(得分:0)

如果希望匹配结果为“true”或“false”,则在标量上下文中进行模式匹配。这就是你在第一个例子中所做的。您执行了模式匹配并将结果分配给标量my($ foo)。所以$ foo得到了“真实”或“虚假”的价值。

但是如果要捕获与模式的一部分匹配的文本,请使用分组括号,然后检查相应的$变量。例如,考虑表达式:

$record =~ /(.*)ing/

“speak”这个词的匹配会将“speak”分配给$ 1,“listen”会将“listen”分配给$ 1等等。这就是你在第二个例子中想要做的事情。麻烦的是你需要添加分组括号。 “$ record =〜/ Defect /”将不会为$ 1分配任何内容,因为模式中没有分组括号。