【问题标题】:Merging two patterns合并两个模式
【发布时间】:2014-07-08 18:52:02
【问题描述】:

我有以下测试文件:

words

words

aa

   word132 b word1 word2 ...
  word131 c word1 word2 word3 word4 ...

bb

words

words

aa

   word132 bi word1 word2 ...
  word131 ci word1 word2 word3 word4 ...

bb

我想在每一列中查找 aa 和 bb 之间的单词。所以想要的结果是:

b
c
bi
ci

我已经设法做到了:

<?php


$pattern = '

words

words

aa

   word132 b word1 word2 ...
  word131 c word1 word2 word3 word4 ...

bb

words

words

aa

   word132 bi word1 word2 ...
  word131 ci word1 word2 word3 word4 ...

bb

';


$result = array();

preg_match_all('/aa\s*(.*)\s*bb/isU',$pattern,$matches);

foreach ($matches[1] as $match) {
    preg_match_all('/(?:\s*)(?:\w+) (\w+) (?:.*)/i',$match, $submatches);    
    foreach ($submatches[1] as $submatch) {
        echo $submatch."<br />";
    }    
}

但如果可能(并且有意义),我希望从我使用的这 2 个搜索模式中创建一个搜索模式。如果我对它们中的每一个都使用其他修饰符,该怎么办?

我在正则表达式方面没有丰富的经验,因此合并这两种模式是否合理,或者对于更复杂的操作,您应该在先前正则表达式的结果上运行正则表达式?

【问题讨论】:

    标签: php regex preg-match pcre


    【解决方案1】:

    更新:您可以使用这个单一的正则表达式:

    if ( preg_match_all(
        '~(?>\baa\b|\G(?<!^))\s*\K^ *\S+ +(\S+).*?$(?=(?:(?!\baa\b).)*?\bbb\b)~sm', $str, $m) )
       print_r($m[1]);
    

    输出:

    Array
    (
        [0] => b
        [1] => c
        [2] => bi
        [3] => ci
    )
    

    * Online regex Demo

    早期解决方案:

    你可以使用preg_replace_callback分2个阶段解决这个问题:

    $arr = array();
    preg_replace_callback('~\baa\n(.*?)\nbb\b~s', function ($m) use (&$arr) {
        if (preg_match_all('~^ *\S+ *(\S+)~m', $m[1], $w)) $arr = array_merge($arr, $w[1]); },
        $str);
    
    print_r($arr);
    

    【讨论】:

    • 这很好,但有没有机会使用一种 PCRE 模式来做到这一点?如果不是,你怎么能猜到使用一种模式无法完成某些事情?
    • 我认为两阶段方法更好的原因是因为 PCRE 不支持像 .NET 这样的可变长度后视。您可以等待更多答案,看看是否有人可以发布一个正则表达式来解决这个问题。不过,我完全赞成让事情变得简单易读。
    • ok,现在检查编辑的代码,用一个 PCRE 正则表达式来解决这个问题。
    • 不,它很漂亮,我喜欢它。本着同样的精神,这个简短的也适用:(?m)^aa(\s*\S* +\K\S+)|\G[^\r\n]*\R+^(?!bb)(?1)或所有格(?m)^aa(\s*+\S*+ ++\K\S++)|\G[^\r\n]*+\R++^(?!bb)(?1)
    • @anubhava 你似乎在嵌套结构中使用(?R) 做得很好。 :) 实际上这个很简单,它不是真正的递归,只是一个子例程:(?1) 只是意味着“再次匹配第 1 组的模式”,所以我们不必再次在正则表达式中粘贴\s*\S* +\K\S+——更干净。 (?(DEFINE)...) 当然是另一种选择,但在这种情况下,IMO 有点矫枉过正。
    猜你喜欢
    • 1970-01-01
    • 2022-07-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多