【问题标题】:Get all occurences between characters to get same result获取字符之间的所有匹配项以获得相同的结果
【发布时间】:2016-05-16 16:31:57
【问题描述】:

我正在查看字符串 3-431 a4-2 4-13 并希望找到 3-431a4-24-13。我使用以下模式:

/(.*-.* )*/gU

我得到了没有问题的预期结果:Online demo

问题是 - 当我想查看以其他一些子字符串开头和结尾的字符串(例如 [])时,如何获得相同的结果。

如果我将主题修改为 [3-431 a4-2 4-13 ] 并将正则表达式修改为 /\[(.*-.* )*\]/gU 我只得到最后一次出现:4-13 并且我没有得到与第一个示例相同的结果。 Online demo

为什么会这样,我该如何解决?

【问题讨论】:

  • 你为什么不用` ` 分割?
  • 你不能用一个正则表达式来做到这一点。在 PCRE 中,量化的捕获组在每次量化的过程中都会被覆盖,只留下组中的最后一个值。我建议使用 \G 构造,但这涉及到每场比赛的冗余(昂贵)前瞻。
  • 简单的方法是捕获内容\[([^\]]+)\],然后解析第1组的值。

标签: php regex preg-match-all pcre


【解决方案1】:

您不需要使用正则表达式,您可以使用explode 或按空格分割:

$str  = "3-431 a4-2 4-13";
$parts = explode(" ", $str);
echo $parts [0]; // 3-431
echo $parts [1]; // a4-2
echo $parts [2]; // 4-13

但是,如果您仍想使用正则表达式,则可以使用:

$re = "/(\\w+-\\w+)/"; 
$str = "3-431 a4-2 4-13"; 

preg_match_all($re, $str, $matches);

Regex demo

顺便说一句,如果你的字符串总是用空格分隔,那么你也可以使用这个正则表达式:

$re = "/(\\S+)/"; 
$str = "3-431 a4-2 4-13"; 

preg_match_all($re, $str, $matches);

Regex demo

另一方面,如果您的字符串以[] 开头和结尾,则为[3-431 a4-2 4-13 ]。这个想法是利用丢弃技术,你可以使用这个正则表达式:

[[\]](*SKIP)(*FAIL)|(\S+)

Working demo

而且,使用preg_split 获得相同的结果:

$exploded = preg_split('[[\]\s]+', '[3-431 a4-2 4-13]', NULL, PREG_SPLIT_NO_EMPTY)

【讨论】:

    【解决方案2】:

    首先,您应该使用.+ 而不是.*,因为+ 意味着至少一次。那么你的正则表达式是:

    /\[(\w+-\w+)*\s*\]/sgU
    

    【讨论】:

    • 您必须将代码(和正则表达式)缩进 4 个空格,否则事情会一团糟。
    【解决方案3】:

    如果您仍想使用正则表达式,这将起作用:

    (^|\])[^[]*\[([^[]*-[^[]* )*(*SKIP)(*FAIL)|(.*-.* )+
    

    基本上,如果发生在[] 之外,它将失败。


    你只得到一个匹配的原因是全局修饰符只会在第一个匹配结束后匹配另一个匹配项,在你的情况下是在右括号之后。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-10-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-03-12
      • 2014-01-04
      • 2015-10-03
      • 1970-01-01
      相关资源
      最近更新 更多