regex - 与/g 修饰符一起使用时级联正则表达式不匹配

标签 regex perl

让我们考虑这个程序:

#!/usr/bin/env perl
use 5.014;
use strict;
use warnings;

my $file = <<END_FILE;
*   Action    : Lorem ipsum
*               Dolor oktam
*               Lorem lorem
*
*   Input     : var1
*               var2
*               var3
*
*   Output    : var4
*               var5
*               var6
END_FILE


$_ = $file;

my ($action, $input) = ('', '');

if (/action\s+:\s*((.|\r\n|\n)*?)(\r\n|\n).*\s*input/gi) {
    say "Action: $1";
}

# Not capture anything
if (/input\s+:\s*((.|\r\n|\n)*?)(\r\n|\n).*\s*output/gi) {
    say "Input: $1";
}

# But this time it works
if ($file =~ /input\s+:\s*((.|\r\n|\n)*?)(\r\n|\n).*\s*output/gi) {
    say "Input OK: $1";
}

# And $_ isn't different from $file
die "WTF!" unless $_ eq $file;

我想在“Action”、“Input”和“Output”之后提取信息。当我尝试在“输入”之后获取信息时,奇怪的事情发生了。如果我使用 $_ 正则表达式不匹配任何东西,但如果我使用 $file 它可以工作,即使 $_ eq $file/p>

我的问题从何而来?

我得到的输出是这样的:

Action: Lorem ipsum
*               Dolor oktam
*               Lorem lorem
*
Input OK: var1
*               var2
*               var3
*

最佳答案

这是因为你使用的是/g,这会让下一次匹配尝试在上一次匹配结束后寻找匹配。由于第一个匹配将消耗 input,第二个匹配将在 input 之后开始,因此永远不会找到另一个要匹配的 input

您可以删除 /g 来解决这个问题。

perlop会告诉你:

The /g modifier specifies global pattern matching--that is, matching as many times as possible within the string. How it behaves depends on the context. In list context, it returns a list of the substrings matched by any capturing parentheses in the regular expression. If there are no parentheses, it returns a list of all the matched strings, as if there were parentheses around the whole pattern.

In scalar context, each execution of m//g finds the next match, returning true if it matches, and false if there is no further match. The position after the last match can be read or set using the pos() function; see pos. A failed match normally resets the search position to the beginning of the string, but you can avoid that by adding the /c modifier (for example, m//gc). Modifying the target string also resets the search position

关于regex - 与/g 修饰符一起使用时级联正则表达式不匹配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26627325/

相关文章:

regex - 消极回顾的替代方案?

perl - 删除一行中字符之间的所有空格而不创建一个巨大的单行

regex - 简单的 Perl 正则表达式解析器

for-loop - 捕捉 "for loop reached last element"的优雅方式?

perl - 将可重定位的 win32 Perl 减少到尽可能少的文件和字节

python - 如何在 Scrapy 中创建基于 href 的 LinkExtractor 规则

html - 如何匹配 `<a>` 标记之前的文本然后返回 `<a>` 节点?

regex - 正则表达式范围 a-Z 中将包含哪些字符?

regex - FOR/F 不适用于批处理文件中的逗号分隔双引号字符串

perl - 新方法何去何从?