【问题标题】:preg_match_all 'OR' operatorpreg_match_all 'OR' 运算符
【发布时间】:2016-05-31 04:28:51
【问题描述】:

我无法从字符串中获取“今天”值。该模式是将字符串放在双花括号内,将字符串放在双花括号外。

我只得到“内部”值。模式是:

/({{(?P<inside>[^}{]+)}}|}}(?P<outside>[^}{]+){{)/

字符串是

{{Friday}}today{{Sunday}}

php代码为:

$returnValue = preg_match_all('/({{(?P<inside>[^}{]+)}}|}}(?P<outside>[^}{]+){{)/', '{{Friday}}today{{Sunday}}', $matches);

这仅返回:

    array (
  0 => 
  array (
    0 => '{{Friday}}',
    1 => '{{Sunday}}',
  ),
  1 => 
  array (
    0 => '{{Friday}}',
    1 => '{{Sunday}}',
  ),
  'inside' => 
  array (
    0 => 'Friday',
    1 => 'Sunday',
  ),
  2 => 
  array (
    0 => 'Friday',
    1 => 'Sunday',
  ),
  'outside' => 
  array (
    0 => '',
    1 => '',
  ),
  3 => 
  array (
    0 => '',
    1 => '',
  ),
)

上面的数组中没有任何关于“今天”的内容。

有趣的是,当模式的各个部分相互替换时,结果中没有“Sunday”或“Suterday”值,而是“today”。

看起来只考虑模式的第一部分。

获取所有值的模式是什么? 谢谢。

已编辑:

1. 感谢非常棒的答案。但我必须稍微扩展一下这个问题。我测试了你的所有提议,它们对字符串很有用

    {{Friday}}today{{Sunday}}

但它们不适用于这样的字符串:

    {{Friday}}t{od{a}y{{Sunday}}

结果中应该是这样的值

t{od{a}y

因为只有双花括号应该是分隔符。

我试图让您的出色模式适应这些要求,但没有成功。子字符串 '}}' 和 '{{' 应该被否定。不仅是单个 '{' 或 '}'。

如何获得?

2. 另一个问题但不是那么重要的是“内部”和“外部”结果数组不应该有空字符串。在图片上看到我的意思: enter image description here

【问题讨论】:

  • 你需要的不是this code吗?只需获取不是{} 的所有内容。或者this one 也应该可以工作。
  • 维克托,这是个好主意。真的很简单。即使它没有将结果分配给“外部”和“内部”键。但这可以在 php.ini 中进行管理。谢谢。
  • 检查this demo。如果这是您需要的,我明天会尽快发布。
  • 干得好。这正是我所需要的。我真的很感谢你的帮助。它甚至适用于这样的字符串:“star t{{Friday}}t{od{a}y{{Sunday}}en d”。

标签: php regex preg-match-all


【解决方案1】:

这里是my solution

$re = "/{{(?<inner>.*?)}}|(?<outer>[^{}]*(?:{(?!{)[^{}]*|}(?!})[^{}]*)*)/"; 
$str = "{{Friday}}today{{Sunday}}"; 
preg_match_all($re, $str, $matches);
print_r(array_filter($matches["outer"]));
print_r(array_filter($matches["inner"]));

为什么看起来如此复杂?

正则表达式包含两种选择,一种是用于将{{}} 中的所有子字符串捕获到“内部”组中,而“外部”组将捕获除{{}} 中的所有子字符串之外的所有子字符串。让我解释一下这些模式:

第 1 部分
{{(?&lt;inner&gt;.*?)}}
这将查找并使用 {{ 子字符串,后跟零个或多个字符而不是换行符(在正则表达式末尾使用 /s dotall 修饰符也匹配换行符),零个或多个出现(使用 .+? 匹配一个或多个),尽可能少(意味着我们停在第一个}})。然后,}} 被匹配。

第 2 部分
(?&lt;outer&gt;[^{}]*(?:{(?!{)[^{}]*|}(?!})[^{}]*)*)
此子模式等于(?&lt;outer&gt;(?:(?!{{(?!{)|}}(?!})).)*),但它是此tempered greedy token 的展开版本(因此比具有2 个替代方案的缓和贪婪令牌更有效)。它只匹配非大括号[^{}]*(零个或多个),然后是{ 的零个或多个序列(=可选匹配),而不是另一个{},而不是另一个},然后零个或多个非大括号。

array_filter 从结果数组中删除空元素。

这是一个regex demo

【讨论】:

    【解决方案2】:

    我已经成功了。空字符串的问题仍然存在。单大括号没有问题。

    (?<={{)(?P<THINGS>((?<!}}).)+)(?=}})|((?<=}})(?P<AREA>((?<!{{).)+)(?={{))|(?P<AREA2>^((?<!{{).)+)(?={{)|(?<=}})(?P<AREA3>((.)+$))
    

    Debuggex Demo

    结果数组:

    大批 ( 0 => 大批 ( 0 => 'Fo{休息', 1 => 'Go{l}d', 2 => '海滩', 3 => '星期一', 4 => '草', 5 => '钻石', 6 => 'S{ea', ), '事情' => 大批 ( 0 => '', 1 => 'Go{l}d', 2 => '', 3 => '星期一', 4 => '', 5 => '钻石', 6 => '', ), 1 => 大批 ( 0 => '', 1 => 'Go{l}d', 2 => '', 3 => '星期一', 4 => '', 5 => '钻石', 6 => '', ), 2 => 大批 ( 0 => '', 1 => 'd', 2 => '', 3 => 'y', 4 => '', 5 => 'd', 6 => '', ), 3 => 大批 ( 0 => '', 1 => '', 2 => '海滩', 3 => '', 4 => '草', 5 => '', 6 => '', ), '面积' => 大批 ( 0 => '', 1 => '', 2 => '海滩', 3 => '', 4 => '草', 5 => '', 6 => '', ), 4 => 大批 ( 0 => '', 1 => '', 2 => '海滩', 3 => '', 4 => '草', 5 => '', 6 => '', ), 5 => 大批 ( 0 => '', 1 => '', 2 => 'h', 3 => '', 4 => 's', 5 => '', 6 => '', ), '区域2' => 大批 ( 0 => 'Fo{休息', 1 => '', 2 => '', 3 => '', 4 => '', 5 => '', 6 => '', ), 6 => 大批 ( 0 => 'Fo{休息', 1 => '', 2 => '', 3 => '', 4 => '', 5 => '', 6 => '', ), 7 => 大批 ( 0 => 't', 1 => '', 2 => '', 3 => '', 4 => '', 5 => '', 6 => '', ), '区域3' => 大批 ( 0 => '', 1 => '', 2 => '', 3 => '', 4 => '', 5 => '', 6 => 'S{ea', ), 8 => 大批 ( 0 => '', 1 => '', 2 => '', 3 => '', 4 => '', 5 => '', 6 => 'S{ea', ), 9 => 大批 ( 0 => '', 1 => '', 2 => '', 3 => '', 4 => '', 5 => '', 6 => 'S{ea', ), 10 => 大批 ( 0 => '', 1 => '', 2 => '', 3 => '', 4 => '', 5 => '', 6 => 'a', ), )

    php代码:

    $returnValue = preg_match_all('/(?<={{)(?P<THINGS>((?<!}}).)+)(?=}})|((?<=}})(?P<AREA>((?<!{{).)+)(?={{))|(?P<AREA2>^((?<!{{).)+)(?={{)|(?<=}})(?P<AREA3>((.)+$))/', 'Fo{rest{{Go{l}d}}Beach{{Monay}}Grass{{Diamond}}S{ea', $matches);
    

    【讨论】:

      【解决方案3】:

      (?&lt;=\{\{)(?&lt;inside&gt;[^\}\{ $]+)|(?&lt;=\}\})(?&lt;outside&gt;[^\{\} $]+)

      DEMO

      如果这对你有用,请告诉我。

      【讨论】:

      • 为什么要在字符类中列出空格和美元符号?
      • 想让它失效,因为我没有得到任何关于输入字符串如何变化的信息,而且外部日期也可能在行/字符串的末尾。
      • 在字符类中,$ 只是一个美元符号。如果要避免匹配行分隔符,请使用\v(垂直空格,包括\r\n,但不包括空格或\t)。要排除 all 空格,请使用 \s(例如 [^{}\s]+)。但我认为这些都没有必要。
      • zolo,谢谢您的回答。我更新了问题。我在要求中添加了两件事。单花括号不应该是分隔符,而只能是 doblye 花括号。也许可以从结果中删除空字符串。
      猜你喜欢
      • 2015-07-08
      • 2020-10-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-23
      相关资源
      最近更新 更多