2015-07-05 2 views
2

я получил следующую строку:preg_match_all все комбинации со словом bounderies

$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";

Теперь я wan't найти слова в этой строке с помощью 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.

Как я могу это сделать? Я думаю, что моя проблема в том, что: «После того, как найден первый матч, последующие поиски продолжаются с конца последнего совпадения».

Update

Это не работает:

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 
) 
+1

Если конкретная часть шаблона регулярного выражения соответствует тексту, то другой шаблон не будет пытаться снова совместить тот же текст. –

ответ

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 )

Функция может быть дополнительно улучшена, чтобы возвращать массивы, если требуются разные случаи для одних и тех же слов или захват смещения.

+0

Спасибо! Эта работа для меня. Не могли бы вы объяснить это немного больше? ;-) – Stefan

+0

@Stefan Отлично, что работает вам: ] Он соответствует каждому элементу '$ arr' отдельно на' $ str'. Здесь не стоит беспокоиться о совпадении матчей. Использование границ слов и сопоставления без оболочки. Функция карты состоит в том, чтобы избежать цикла foreach. '$ res' array задается с возвращенным совпадением или' false'. False элементы фильтруются и, наконец, сортируются/ключи переиндексированы (что может и не понадобиться). –

1

Вы можете использовать предпросмотр, чтобы получить ваши ovelaping матчи:

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


Update: на основе обновленной фрагменте кода вы можете сделать это:

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 
     ) 
) 
+0

Но это не сработает, когда изменения в регулярном выражении: (? = \ B (abituria | absolvia | adel | adel sachsen | sachsen | könig) \ b) Можете ли вы исправить это? – Stefan

+0

[Он еще здесь, в демо] (https://regex101.com/r/pT1sI1/3) – anubhava

+0

Но не в PHP .. я получил: Array ( [0] => König [1] => Sachsen [2] => Adel [3] => Sachsen ) – Stefan

0

Как вы уже заметили, preg_match_all продолжает поиск после конец каждого последнего совпадения, поэтому это не лучший инструмент для вашей задачи.

Простым, но менее эффективным решением было бы сделать один preg_match для каждого отдельного поискового запроса.

Если строки не намного длиннее вашего примера, я бы пошел на это, оптимизируя его, кажется, не стоит того.

Если производительность действительно критическая, я бы группа префиксы других терминов с ними, при заказе каждой группы длинного срока первого:

  • abituria
  • absolvia
  • Adel Sachsen, Adel
  • Sachsen
  • könig

Нет ж использовать регулярное выражение с опережением утверждением:

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

Если $string содержит «Аделя», а не «Adel Sachsen», он будет соответствовать правильно. Если он содержит «adel sachsen», он будет соответствовать только «adel sachsen», но из групп, которые мы создали ранее, мы знаем, что он также соответствует префиксам «adel sachsen», то есть «adel».

Смежные вопросы