preg_match_all所有与单词bounderies的组合

时间:2015-07-05 09:59:20

标签: php regex

我有以下字符串:

$string = "König Friedrich August III. von Sachsen - Adel Sachsen, Waidmannsheil, Kapitaler 16ender erlegt auf der Jagd am 2. Oktober 1905, gelaufen 30.06.1909, Verlag, Karlowa Walter, Dresden";

现在我不想使用preg_match_all找到该字符串中的单词:

preg_match_all("/\b(abituria)\b|\b(absolvia)\b|\b(adel sachsen)\b|\b(adel)\b|\b(sachsen)\b|\b(könig)\b/i",$string,$matches);

字符串仅匹配

array(
  0 => "König",
  1 => "Adel Sachsen"
)

但我需要它还会在$ matches-Array中返回“Adel”。

我该怎么做?我认为我的问题是:“在找到第一场比赛后,后续搜索将从最后一场比赛结束时继续。”

更新

这不起作用:

preg_match_all('/(?=\b(adel sachsen|adel)\b)/ui', $string, $matches);
print_r($matches[1]);

Array
(
    [0] => Adel Sachsen
)


preg_match_all('/(?=\b(adel|adel sachsen)\b)/ui', $string, $matches);
print_r($matches[1]);

Array
(
    [0] => Adel
)

但我需要以下结果:

Array
(
    [0] => Adel Sachsen,
    [1] => Adel
)

3 个答案:

答案 0 :(得分:2)

我只搜索每个单词/组合(为每个单词/组合生成一个模式)和map根据匹配结果数组或设置为false,如果它不匹配。然后filter假元素:

$arr = ["nadel", "adel", "knödel", "sachsen", "adel sachsen"];

$str = "Friedrich August III. von Sachsen - Adel Sachsen";

$res = array_filter(array_map(function ($s) use (&$str) {
       $s = '/\b'.preg_quote($s,'/').'\b/iu';
       return preg_match($s, $str, $out) ? $out[0] : false; }, $arr));

sort($res); print_r($res);

See test at eval.in匿名函数与array_map:至少需要PHP 5.3

  

阵   (       [0] => Adel       [1] => Adel Sachsen       [2] => Sachsen   )

如果需要相同单词的不同情况或捕获偏移量,可以进一步改进函数以返回数组。

答案 1 :(得分:1)

你可以使用前瞻来获得你的过度匹配:

preg_match_all('/(?=\b(abituria|absolvia|adel sachsen|adel|sachsen|könig)\b)/ui',
         $string, $matches);

print_r($matches[1]);
Array
(
    [0] => König
    [1] => Sachsen
    [2] => Adel Sachsen
    [3] => Sachsen
)

RegEx Demo

更新:根据您更新的代码段,您可以执行以下操作:

 preg_match_all('/(?=\b(adel sachsen)\b)(?=\b(adel)\b)/ui', $string, $matches); 
 unset($matches[0]);
 print_r($matches);

<强>输出:

Array
(
    [1] => Array
        (
            [0] => Adel Sachsen
        )

    [2] => Array
        (
            [0] => Adel
        )
)

答案 2 :(得分:0)

正如您已经注意到的那样,preg_match_all会在每个最后一场比赛结束后继续搜索,因此它不是您工作的最佳工具。

简单但性能较低的解决方案是为每个搜索字词执行一次preg_match

如果字符串不比你的例子长,我会这样做,优化它似乎不值得。

如果表现真的很重要,我会将其他条款的前缀与它们分组,先按最长词排序每组:

  • abituria
  • absolvia
  • adel sachsen,adel
  • 萨克森
  • 柯尼希

现在使用前瞻断言的正则表达式:

preg_match_all('/(?=\b(abituria|absolvia|adel sachsen|adel|sachsen|könig)\b)/ui',
     $string, $matches);

如果$string包含“adel”,但不包含“adel sachsen”,则会正确匹配。如果它包含“adel sachsen”,它只会匹配“adel sachsen”,但是从我们之前构建的组中,我们知道它也匹配“adel sachsen”的前缀,即“adel”。