这一点必须明显,但我只是没有看到它。
我有一份包含数千条记录的文件,如下所示:
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”完美无缺。
我真的很困惑为什么我的比赛的回报如此棘手。 任何帮助将不胜感激。
答案 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
别名,因此经常使用1
和undef
:但是,它可以很好地可以是其他值而不会使文档不正确。
$1
,因为没有捕获组:可能需要$&
(aka $MATCH
)吗? (或者更好的是,将正则表达式更改为具有捕获组; - )
快乐的编码。
答案 4 :(得分:1)
my($foo) = $record=~ /Defect/;
print STDOUT $foo;
而不是这样你应该做
$record =~ /Defect/;
my $foo = $&; # Matched portion of the $record.
因为你的目标似乎是获得匹配的部分。 返回值为true / false,表示匹配是否成功。
答案 5 :(得分:0)
如果希望匹配结果为“true”或“false”,则在标量上下文中进行模式匹配。这就是你在第一个例子中所做的。您执行了模式匹配并将结果分配给标量my($ foo)。所以$ foo得到了“真实”或“虚假”的价值。
但是如果要捕获与模式的一部分匹配的文本,请使用分组括号,然后检查相应的$变量。例如,考虑表达式:
$record =~ /(.*)ing/
“speak”这个词的匹配会将“speak”分配给$ 1,“listen”会将“listen”分配给$ 1等等。这就是你在第二个例子中想要做的事情。麻烦的是你需要添加分组括号。 “$ record =〜/ Defect /”将不会为$ 1分配任何内容,因为模式中没有分组括号。