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

发布于 2024-12-11 16:43:19 字数 676 浏览 0 评论 0原文

这一定是显而易见的,但我只是没有看到它。

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

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;

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

或者:

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

完全不打印任何内容。

$record =~ s/Defect/Blefect/

另一方面,将用“Blefect”替换“Defect”则完全没问题。

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

This has got to be obvious but I'm just not seeing it.

I have a documents containing thousands of records just like below:

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

I've managed to get each record separated and I'm now trying to parse out each field.

I'm trying to match the numbered headers so that I can pull out the data that succeeds them but the problem is that my matches are only returning me "1" when they succeed and nothing if they don't. This is happening for any match I try to apply.

For instance, applied to a simple word within each record:

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

prints out out a "1" for each record if it contains "Defect" and nothing if it contains something else.

Alternatively:

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

prints absolutely nothing.

$record =~ s/Defect/Blefect/

will replace "Defect" with "Blefect" perfectly fine on the other hand.

I'm really confused as to why the returns on my matches are so screwy.
Any help would be much appreciated.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

烟─花易冷 2024-12-18 16:43:19

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

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

You need to use capturing parentheses to actually capture:

if ($record =~ /(Defect)/ ) {
    print "$1\n";
}
奶茶白久 2024-12-18 16:43:19

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

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

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

I think what you really want is to wrap the regex in parentheses:

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

In list context, the groups are returned, not the match itself. And your original code has no groups.

凉风有信 2024-12-18 16:43:19

=~ perl 运算符采用一个字符串(左操作数)和一个正则表达式(右操作数),并将该字符串与 RE 进行匹配,根据 re 是否匹配返回一个布尔值(true 或 false) 。

现在 Perl 并没有真正的布尔类型——相反,在布尔上下文中,每个值(任何类型)都被视为“true”或“false”——大多数情况都是“true”,但空字符串和未定义事物的特殊“undef”值为 false。因此,当返回布尔值时,它通常使用“1”表示 true,使用“”(空字符串)表示 false。

现在关于你的最后一个问题,尝试打印 $1 不会打印任何内容。每当您匹配正则表达式时,perl 都会将 $1$2 ... 设置为 RE 中带括号的子表达式的值。然而,在您的示例中,没有带括号的子表达式,因此 $1 始终为空。如果将其更改为,

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

您将得到更像您期望的内容(如果匹配,则为 Defect;如果不匹配,则什么也没有)。

我通常看到的最常见的正则表达式匹配习惯是这样的:

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
}

The =~ perl operator takes a string (left operand) and a regular expression (right operand) and matches the string against the RE, returning a boolean value (true or false) depending on whether the re matches.

Now perl doesn't really have a boolean type -- instead every value (of any type) is treated as either 'true' or 'false' when in a boolean context -- most things are 'true', but the empty string and the special 'undef' value for undefined things are false. So when returning a boolean, it generall uses '1' for true and '' (empty string) for false.

Now as to your last question, where trying to print $1 prints nothing. Whenever you match a regular expression, perl sets $1, $2 ... to the values of parenthesized subexpressions withing the RE. In your example however, there are NO parenthesized sub expressions, so $1 is always empty. If you change it to

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

You'll get something more like what you expect (Defect if it matches and nothing if it doesn't).

The most common idiom for regexp matching I generally see is something like:

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
}
ゞ记忆︶ㄣ 2024-12-18 16:43:19

来自 perlop、Quote 和 Quote-Like 运算符 [括号中的位是我添加的]:

/模式/msixpodualgc

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

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

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

$1 永远不会被定义,因为没有捕获组:也许 $& ; (又名 $MATCH 是需要的吗? (或者更好的是,更改正则表达式以具有捕获组;-)

快乐编码。

From perlop, Quote and Quote-Like operators [bits in brackets added by me]:

/PATTERN/msixpodualgc

Searches a string for a pattern match, and in scalar context returns true [1] if it succeeds, false [undef] if it fails.

(Looking at the section on s/// will also be useful ;-)

Perl just doesn't have a discreet boolean type or true/false aliases so 1 and undef are often used: however, it could very well could be other values without making the documentation incorrect.

$1 will never be defined because there is no capture group: perhaps $& (aka $MATCH) is desired? (Or better, change the regular expression to have a capture group ;-)

Happy coding.

橘和柠 2024-12-18 16:43:19
my($foo) = $record=~ /Defect/;
print STDOUT $foo;

相反,您应该这样做

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

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

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

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

Rather than this you should do

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

As your goal seems to be to get the matched portion.
The return value is true/false indicating if match was successful or not.

You may find http://perldoc.perl.org/perlreref.html handy.

往昔成烟 2024-12-18 16:43:19

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

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

$record =~ /(.*)ing/

“speaking”一词的匹配会将“speak”分配给 $1,“listening”会将“listen”分配给 $1,等等。这就是您在第二个示例中尝试执行的操作。问题是您需要添加分组括号。 “$record =~ /Defect/” 不会向 $1 分配任何内容,因为模式中没有分组括号。

If you want the result of a match as "true" or "false", then do the pattern match in scalar context. That's what you did in your first example. You performed a pattern match and assigned the result to the scalar my($foo). So $foo got a "true" or "false" value.

But if you want to capture the text that matched a part of your pattern, use grouping parentheses and then check the corresponding $ variable. For example, consider the expression:

$record =~ /(.*)ing/

A match on the word "speaking" will assign "speak" to $1, "listening" will assign "listen" to $1, etc. That's what you are trying to do in your second example. The trouble is that you need to add in the grouping parentheses. "$record =~ /Defect/" will assign nothing to $1 because there are no grouping parentheses in the pattern.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文