有没有一种方法可以跨多行编写正则表达式模式?

4

我经常使用超级复杂和长的正则表达式。使用PHP的PCRE。

很长一段时间以来,我一直在寻找一种类似于:

    preg_match('#blablabla...
blablablablablabla...
blablablablablabla...
blablablablablabla...
blablablablablabla...
blablablablablabla...
blablablablablabla...
blablablablablabla...
blablablablablabla...
blablablablablabla...
blablablablablabla...
blablabla#uis');

改为:

preg_match('#blablabla...blablablablablabla...blablablablablabla...blablablablablabla...blablablablablabla...blablablablablabla...blablablablablabla...blablablablablabla...blablablablablabla...blablablablablabla...blablablablablabla...blablabla#uis');

如果我添加实际的换行符,那么它将成为正则表达式的一部分。也许不是作为实际的换行符,而是作为空格。除非我完全错了。

有没有一些字符可以在每行末尾使用以表示:“这应该是一行”?


仅凭直觉,您可以将模式放入变量中(在此处编写),并在将其馈送到正则表达式函数时删除换行符。 - El_Vanja
使用 NOWDOC/HEREDOC 字符串字面量,并使用 /x 修饰符。但您需要记得转义字面上的空格和 # - Wiktor Stribiżew
我建议将标题编辑为更易于搜索的内容,例如 “如何在多行上编写正则表达式模式”。我认为这是一个很好的问题,并且从长远来看,它将从一个更准确的标题中受益。 - El_Vanja
1个回答

2
您可以使用支持变量插值的HEREDOC(或不支持变量插值的NOWDOC),并使用x标志(修饰符)。请查看文档对量词的说明:

x(PCRE_EXTENDED)
如果设置了此修饰符,则模式中的空格数据字符将完全忽略,除非在字符类内或已转义,以及在未转义的#和下一个换行符之间的字符(包括换行符)也将被忽略。这相当于Perl的/x修饰符,并使得在复杂的模式中包含注释成为可能。但是,请注意,这仅适用于数据字符。空格字符永远不能出现在模式中的特殊字符序列中,例如在引入条件子模式的(?(序列中。

// HEREDOC
$pattern_with_interpolation = <<<EOD
/
blablabla...  # comment here
blablabla     # comment here
/uisx
EOD;

// NOWDOC
$pattern_without_interpolation = <<<'EOD'
/blablabla... # comment here
blablabla     # comment here
/uisx
EOD;

请注意,您需要在模式中转义所有的#和字面上的空格字符,因为/x标志允许在#之后的行尾使用注释,并插入任何具有格式意义的字面上的空格,它们不匹配相应的字符。
示例:
$pattern_without_interpolation = <<<'EOD'
/
\d+      # one or more digits
\        # a single space
\p{L}+   # one or more letters
\#       # a literal hash symbol
/ux
EOD;
if (preg_match($pattern_without_interpolation, '1 pound#', $m)) {
    echo $m[0];
}
// => 1 pound#

查看 PHP演示

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接