Свести массив регулярных выражений

У меня есть массив регулярных выражений - $ toks:

Array
(
    [0] => /(?=\D*\d)/
    [1] => /\b(waiting)\b/i
    [2] => /^(\w+)/
    [3] => /\b(responce)\b/i
    [4] => /\b(from)\b/i
    [5] => /\|/
    [6] => /\b(to)\b/i
)

Когда я пытаюсь его сгладить:

$patterns_flattened = implode('|', $toks); 

Я получаю регулярное выражение:

/(?=\D*\d)/|/\b(waiting)\b/i|/^(\w+)/|/\b(responce)\b/i|/\b(from)\b/i|/\|/|/\b(to)\b/i

Когда я пытаюсь:

if (preg_match('/'. $patterns_flattened .'/', 'I'm waiting for a response from', $matches)) {
    print_r($matches);  
}
  • Я получаю сообщение об ошибке:

    Предупреждение: preg_match (): Unknown modifier '(' in ... index.php on line

В чем моя ошибка? Спасибо.

Ваше регулярное выражение должно быть между //, поэтому вам нужно удалить // из каждого значения массива, также удалить "i", что означает нечувствительность к регистру, и поместить его после // i, и все данные из массива взорвутся между / implode ()/я

Aleksandar Rakić 26.10.2018 09:04

@ user889349 Почему бы не зациклить массив и не проверить каждое регулярное выражение?

splash58 26.10.2018 09:23

@ splash58 Это было бы намного медленнее, ИМХО

Ethan 26.10.2018 09:30

но OP теперь должен быть уверен, что удаление таких опций, как /i, не изменяет логику регулярного выражения.

splash58 26.10.2018 09:33
0
4
227
3

Ответы 3

Вам нужно удалить открывающую и закрывающую косую черту, например:

$toks = [
    '(?=\D*\d)',
    '\b(waiting)\b',
    '^(\w+)',
    '\b(response)\b',
    '\b(from)\b',
    '\|',
    '\b(to)\b',
];

И затем, я думаю, вы захотите использовать preg_match_all вместо preg_match:

$patterns_flattened = implode('|', $toks);
if (preg_match_all("/$patterns_flattened/i", "I'm waiting for a response from", $matches)) {
    print_r($matches[0]);
}

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

Array
(
    [0] => I
    [1] => waiting
    [2] => response
    [3] => from
)

Попробуйте на 3v41.org

   <?php

$data = Array
(
0 => '/(?=\D*\d)/',
1 => '/\b(waiting)\b/i',
2 => '/^(\w+)/',
3 => '/\b(responce)\b/i',
4 => '/\b(from)\b/i',
5 => '/\|/',
6 => '/\b(to)\b/i/'
);


$patterns_flattened = implode('|', $data);

$regex = str_replace("/i",'',$patterns_flattened);
$regex = str_replace('/','',$regex);

if (preg_match_all(  '/'.$regex.'/', "I'm waiting for a responce from", $matches)) {
    echo '<pre>';
print_r($matches[0]);
}

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

Вот действительно хороший инструмент для проверки вашего регулярного выражения:

https://regexr.com/

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

Вывод приведенного выше кода:

  Array
(
    [0] => I
    [1] => waiting
    [2] => responce
    [3] => from
)

Есть несколько настроек, которые необходимо сделать с вашим массивом $tok.

  1. Чтобы удалить ошибку, вам необходимо удалить разделители шаблонов и модификаторы шаблонов из каждого элемента массива.
  2. Никакая группировка захвата не требуется, на самом деле это приведет к увеличению количества шагов и приведет к ненужному раздуванию выходного массива.
  3. Какими бы ни были ваши намерения с (?=\D*\d), его нужно переосмыслить. Если где-то в вашей строке ввода есть число, вы потенциально собираетесь сгенерировать множество пустых элементов, которые, безусловно, не принесут пользы вашему проекту. Посмотри что происходит, когда я помещаю пробел, а затем 1 после from в строке ввода.

Вот моя рекомендация: (Демо PHP)

$toks = [
    '\bwaiting\b',
    '^\w+',
    '\bresponse\b',
    '\bfrom\b',
    '\|',
    '\bto\b',
];

$pattern = '/' . implode('|', $toks) . '/i';
var_export(preg_match_all($pattern, "I'm waiting for a response from", $out) ? $out[0] : null);

Выход:

array (
  0 => 'I',
  1 => 'waiting',
  2 => 'response',
  3 => 'from',
)

Другие вопросы по теме