【问题标题】:Is start ^ and end $ required for multiple regex patterns多个正则表达式模式是否需要 start ^ 和 end $
【发布时间】:2018-03-29 15:21:45
【问题描述】:

如果给定[name=anystring]#anystring,其中anystring 是一个已删除任何空格的字符串,我希望返回anystring

在尝试两者之前,我都成功地单独执行了它们。

$pattern = "/^#(.+)$/";
preg_match($pattern, '#anystring', $matches);
preg_match($pattern, '[name=anystring]', $matches);

$pattern = "/^\\[name=(.+)\\]$/";
preg_match($pattern, '#anystring', $matches);
preg_match($pattern, '[name=anystring]', $matches);

然后我尝试将它们结合起来。

# with start ^ and end $ on both
$pattern = "/^#(.+)$|^\\[name=(.+)\\]$/";
preg_match($pattern, '#anystring', $matches);
preg_match($pattern, '[name=anystring]', $matches);

# without start ^ and end $ on both
$pattern = "/^#(.+)|\\[name=(.+)\\]$/";
preg_match($pattern, '#anystring', $matches);
preg_match($pattern, '[name=anystring]', $matches);

虽然我“有点”得到了我正在寻找的东西,但第二个模式 [name=(.+)] 返回一个包含三个元素的数组。

我应该在第一个模式之后拥有并结束$,并在第二个模式之前开始^?这会导致第二个模式返回一个包含三个元素的数组吗?

编辑。展示一个版本如何显示更多的数组元素

<?php

$pattern = "/^(?:#(.+)|\\[name=(.+)\\])$/s";
preg_match($pattern, '#anystring', $matches);
print_r($matches);
preg_match($pattern, '[name=anystring]', $matches);
print_r($matches);

(
    [0] =&gt; #anystring
    [1] =&gt; anystring
)
Array
(
    [0] =&gt; [name=anystring]
    [1] =&gt; 
    [2] =&gt; anystring
)

【问题讨论】:

  • 哦,我想我看到了问题的一部分。我想我应该只有一个(....)
  • . 不匹配 \n 因此,假设您没有打开 s (单行模式)标志,您的 .+ 正则表达式将仅匹配给定的行。您可以将 ^ 添加到您的模式中,以强制它每次都从字符串的开头开始(否则它将继续尝试字符串中的每个字符,直到找到匹配项)但这取决于您
  • -我应该有开始和结束锚点吗? +仅当您需要您的正则表达式匹配您的整个输入字符串时。
  • @revo 是的,我确实需要。由于我有两种模式,这两种模式都需要单独吗?
  • 不,他们不需要。将它们分组^(?:#(.+)|\\[name=(.+)\\])$

标签: php regex preg-match pcre


【解决方案1】:

您正在寻找一个branch reset group,其中捕获组的编号从组之前的最后一个 ID 开始:

^(?|#(.+)|\[name=(.+)])$
  ^^

regex demo

详情

  • ^ - 字符串开头
  • (?| - 分支重置组的开始
    • #(.+) - # 然后第 1 组捕获 1+ 个字符,尽可能多
    • | - 或
    • \[name= - [name= 子字符串
    • (.+) - 第 1 组(再次)匹配除换行符以外的 1+ 个字符,尽可能多
    • ] - 一个]
  • ) - 分支重置组结束
  • $- 字符串结束。

【讨论】:

  • 啊,都返回两个元素数组。我本来可以处理三个,但这让我很烦。请问首字母?是干什么用的?编辑。没关系。你刚刚回答!
  • @user1032531 它是分组结构的一部分。 (?|...|...|....) 是构造方案。
【解决方案2】:

您可以使用非捕获组组合 2 个正则表达式:

(?:pattern1|pattern2)

我写了这个正则表达式,它将捕获两个字符串:

(?:\[\w+=(?&lt;bracketword&gt;\w+)\]|\#(?&lt;word&gt;\w+))

您的匹配项将包含数组关键字括号词或单词。 在下面的 regex101 链接上查看。

https://regex101.com/r/AmgHTS/1/

如果您愿意,也可以使用开始和结束字符串 ^ 和 $。在我编辑的正则表达式中,我的测试字符串是两行(每个字符串一行),所以我也必须使用多行标志。

https://regex101.com/r/AmgHTS/2/

【讨论】:

  • 感谢 delboy,在 regex101 链接中,指定的多行标志在哪里。当我在 php 中使用你的模式时,我仍然得到一个三元素数组,所以我一定没有正确使用这个标志。
  • 我的正则表达式使用命名的捕获组,所以它应该是 $matches['bracketword'] 或 $matches['word']
  • 我认为你的字符串不会是多行的。如果您删除其中一个测试字符串和多行标志,它应该可以工作
  • 啊,那些旗帜瞒着我!原来 PHP 不喜欢 g。我编辑了我的原始帖子以显示如何返回两个或三个元素。虽然使用像 wordbracketword 这样的标签很好,但我希望发现它无法完成相同的单词,所以接下来我想返回一个具有相同数量元素的数组。
【解决方案3】:

仅捕获 anything 并同时使用 Lookbehind,如下所示:

(?<=#|name=)([^\[#\]]+)

https://regex101.com/r/AmgHTS/4/

更多检查:

https://regex101.com/r/AmgHTS/5

【讨论】:

  • 也可以。为什么此解决方案不需要 .+\w 之类的东西?
  • @user1032531 当你写 [^something]+ 这意味着它是 (.+) 除了一些东西
猜你喜欢
  • 2013-07-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-01
  • 2022-12-03
相关资源
最近更新 更多