【问题标题】:RegEx for capturing groups between repeated words用于捕获重复单词之间的组的正则表达式
【发布时间】:2019-05-13 21:24:40
【问题描述】:

关键字是“*OR”或“*AND”。

假设我有下面的字符串:

这是一个带有特殊字符的 t3xt,例如 !#。 *并且这是 另一个带有特殊字符的文本 *AND 这重复 *OR 不要 重复 *OR 有更多的字符串 *AND 以这个字符串结束。

我想要以下

group1 "This is a t3xt with special characters like !#."  
group2 "*AND"  
group3 "and this is another text with special characters"  
group4 "*AND"  
group5 "this repeats"  
group6 "*OR"  
group7 "do not repeat"  
group8 "*OR"  
group9 "have more strings"  
group10 "*AND"  
group11 "finish with this string."  

我试过这样:

(.+?)(\*AND\*OR)

但它只获取第一个字符串,然后我需要不断重复代码以收集其他字符串,但问题是有些字符串只有一个 *AND,或者只有一个 *OR 或几十个,即很随意。而且下面的正则表达式也不起作用:

((.+?)(\*AND\*OR))+

例如:

这是一个带有特殊字符的 t3xt,例如 !#。 *并且这是 另一个带有特殊字符的文本

【问题讨论】:

  • 请指定语言/正则表达式引擎。此外,为您的示例和预期匹配使用格式/标记可能有助于我们更好地了解您要完成的工作。
  • 我已插入预期的匹配项。我正在使用 php7。

标签: php regex preg-match pcre


【解决方案1】:

PHP 有一个preg_split 函数来处理这类事情。 preg_split 允许您通过可以定义为正则表达式模式的分隔符拆分字符串。此外,它还有一个参数允许您在匹配/拆分结果中包含匹配的分隔符。

因此,不是编写正则表达式来匹配全文,而是正则表达式用于分隔符本身。

示例:

$string = "This is a t3xt with special characters like !#. *AND and this is another text with special characters *AND this repeats *OR do not repeat *OR have more strings *AND finish with this string.";
$string = preg_split('~(\*(?:AND|OR))~',$string,0,PREG_SPLIT_DELIM_CAPTURE);
print_r($string);

输出:

Array
(
    [0] => This is a t3xt with special characters like !#. 
    [1] => *AND
    [2] =>  and this is another text with special characters 
    [3] => *AND
    [4] =>  this repeats 
    [5] => *OR
    [6] =>  do not repeat 
    [7] => *OR
    [8] =>  have more strings 
    [9] => *AND
    [10] =>  finish with this string.
)

但如果您真的想坚持使用preg_match,则需要使用preg_match_all,它类似于preg_match(您在问题中标记的内容),除了它会进行全局/重复匹配.

示例:

$string = "This is a t3xt with special characters like !#. *AND and this is another text with special characters *AND this repeats *OR do not repeat *OR have more strings *AND finish with this string.";
preg_match_all('~(?:(?:(?!\*(?:AND|OR)).)+)|(?:\*(?:AND|OR))~',$string,$matches);
print_r($matches);

输出:

Array
(
    [0] => Array
        (
            [0] => This is a t3xt with special characters like !#. 
            [1] => *AND
            [2] =>  and this is another text with special characters 
            [3] => *AND
            [4] =>  this repeats 
            [5] => *OR
            [6] =>  do not repeat 
            [7] => *OR
            [8] =>  have more strings 
            [9] => *AND
            [10] =>  finish with this string.
        )

)

首先,请注意,与preg_split 不同,preg_match_all(和preg_match)返回多维度数组,而不是单维度数组。其次,从技术上讲,我使用的模式可以简化一点,但代价是必须在返回的多维数组中引用多个数组(一个数组用于匹配的文本,另一个数组用于匹配的分隔符) ,然后您将不得不循环并替换参考; IOW 将进行额外的清理以获得具有两个匹配集的最终单个数组,如上所述。

我只展示这种方法是因为您在技术上要求在您的问题中使用它,但我建议使用preg_split,因为它消除了很多这种开销,以及为什么首先创建它(以更好地解决方案像这样)。

【讨论】:

  • 非常感谢,效果很好。我只是不明白图案上的波浪号的含义。
  • @AndersonOliveira 是模式分隔符。 PHP preg_xxx 函数可以使用许多不同的符号作为模式分隔符。最常用的一种是/ 正斜杠。我个人使用波浪号,因为这样我在执行基于 URL 或目录的模式时不必转义 /,而且它对我来说也更加突出。
  • preg_xxx 函数的第一个参数期望使用分隔符来表示模式的开始和结束,因为标志也被放入字符串中。例如,将第一个参数更改为 '~(\*(?:AND|OR))~i'(末尾带有 i)将使匹配不区分大小写。
  • 知道了@CrayonViolent,感谢您的解释!
猜你喜欢
  • 2017-11-18
  • 2019-10-13
  • 2020-06-09
  • 1970-01-01
  • 2019-06-23
  • 1970-01-01
  • 2018-07-23
  • 2017-09-13
  • 2011-03-11
相关资源
最近更新 更多