PHP preg заменяет несколько правил


Мне просто интересно, как применить несколько правил для preg_replace, не выполняя их в первом запуске. Это немного сложно, позвольте мне объяснить на примере.

Ввод:

$string = 'The quick brown fox jumps over the lazy freaky dog'; 

Правила:

  • заменить a, я ... , o с u (если не в начале слова и если не перед / после гласной)
  • заменить e, u с i (если не в начале слова и если нет до / после гласной)
  • заменить ea на i (если не в начале слова)
  • замените целые слова ie dog на cat и fox на wolf (без применения правил выше)

Вывод: Thi quick bruwn wolf jimps over thi luzy friky cat




Я начал с чего-то вроде этого: (отредактировано благодаря Ezequiel Muns )

$patterns = array();
$replacements = array();

$patterns[] = "/(?<!b|[aeiou])[aio](?![aeiou])/";
$replacements[] = "u";

$patterns[] = "/(?<!b|[aeiou])[eu](?![aeiou])/";
$replacements[] = "i";

$patterns[] = '/ea/';
$replacements[1] = 'i';

$patterns[] = '/dog/';
$replacements[0] = 'cat';

echo preg_replace($patterns, $replacements, $string);

Вывод:

Thi qiick briwn fix jimps ivir thi lizy friiky dig



отредактировано:

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

Пример ' Фокс':

  1. правило: превращает fox в fux
  2. правило: превращает fux в fix

Есть ли способ избежать следующего правила(правил), если символ уже был введен предыдущим правилом?

Имеет ли это смысл?

1 2

1 ответ:

Во-первых, вы должны быть ясны относительно условий замены, ваши правила говорят "не в начале слова и не до/после гласной", но вы не реализовали это в регулярном выражении. Вы можете сделать это с помощью отрицательного Lookahead/Lookbehind. Например:

  1. заменить a, i, o на u (если не в начале слова и если не перед / после гласной)

Можно реализовать с помощью:

$patterns[] = "/(?<!\b|[aeiou])[aio](?![aeiou])/";
$replacements[] = "u";
Этот метод может быть использован для реализации первых 3 Правил.

В следующая проблема заключается в том, что "лиса" и "собака" будут затронуты первыми 3 правилами, поэтому вы должны заменить измененную версию на "волк" и "кошка". Итак, для собаки = > кошки:

$patterns[] = "/\bdug\b/";
$replacements[] = "cat";

Примечание: из-за того, как preg_replace работает с массивами, гораздо лучше не использовать индексы в массивах $patterns и $replacements, так как они могут вводить в заблуждение. Используйте оператор [] в парах, как я сделал выше, так что вы всегда знаете, что идет с чем.

Часть 2:

Ага. Я вижу. Вам нужно сделайте замену исключительной.

Можно использовать регулярное выражение, соответствующее обоим первым случаям, которые являются проблемными. Затем вы можете использовать интересную странную особенность preg_replace: когда вы добавляете модификатор e, строка замены вместо этого оценивается как PHP-код. Комбинируя это с группами захвата, вы сможете решить, выводить ли u или i в соответствии с тем, что вы сопоставили.

$patterns[] = "/(?<!\b|[aeiou])([aeiou])(?![aeiou])/e";
$replacements[] = '("$1" == "e" || "$1" == "u")? "i":"u"';

*Обратите внимание на /e и () вокруг класса соответствия гласных.