2016-06-15 2 views
0

Я знаю, что это наивный вопрос, но регулярное выражение всегда сбивает меня с толку.Regex for PHP preg_replace, чтобы найти числа между тегами

Я хочу заменить цифры в строке, если они находятся между тегом, здесь скобки.

$str = " Some text 11 have number 12 (11,12,13)"; 

$array = array(1 => 'one', 2 => 'two', 11 => 'eleven', 12 => 'twelve', 13 => 'thirteen'); 

foreach ($array as $key => $value) { 
$str = preg_replace('regex to match $key', $value, $str); 
} 

Результат должен быть

$str = " Some text 11 have number 12 (eleven,twelve,thirteen)"; 

Я борюсь с регулярными выражениями шаблона, чтобы соответствовать номеру, который должен быть в круглых скобках. В скобках указаны только цифры и ,.

+4

Да, я не думаю, что '' регулярное выражение для соответствия $ key'' - ваша лучшая попытка. Ожидается, что вы получите помощь с вашим кодом, а не получите все для вас. –

+0

@ ÁlvaroGonzález Что отсутствует в коде, кроме шаблона регулярного выражения?!?!? – Googlebot

+0

Хорошо, я дам вам пару советов, которые нужно начать: 1) Первый аргумент 'preg_replace()' должен включать как выражение, так и модификаторы, поэтому вам нужно использовать ограничители, например. ''/ foo /'' 2) Функция возвращает замененную строку и не изменяет исходное значение, поэтому вы должны где-то сохранить возвращаемое значение. - Вы можете найти примеры использования в руководстве по PHP http://php.net/preg_replace –

ответ

4

Я предлагаю использовать регулярное выражение, которое находит все последовательные номера (цифры), разделенный фрагмент памяти с запятой после открытия (. Затем совпадения могут быть переданы в preg_replace_callback, и если соответствующий символ присутствует в массиве, замените его соответствующим значением, иначе просто верните совпадение.

Вот регулярное выражение:

(?:\G(?!\A)|\(),?\K\d+ 

См regex demo

Детали:

  • (?:\G(?!\A)|\() - Совпадает положение предыдущего успешного матча (\G(?!\A)) или ( символ
  • ,? - необязательный (1 или 0) запятая
  • \K - оператор отбрасывая весь текст соответствует до сих пор
  • \d+ - 1 или более цифр (единственный текст, который мы имеем в матче вернулся).

А вот PHP code:

$re = '/(?:\G(?!\A)|\(),?\K\d+/'; 
$str = "Some text 11 have number 12 (9,11,12,13)"; 
$array = array(11 => 'eleven', 12 => 'twelve', 13 => 'thirteen'); 

echo $result = preg_replace_callback($re, function ($m) use ($array) { 
    return !empty($array[$m[0]]) ? $array[$m[0]] : $m[0]; 
}, $str) . PHP_EOL; 

В результате Some text 11 have number 12 (9,eleven,twelve,thirteen) в 9 отсутствует в $array.

+0

Это невероятно тонкое! – Googlebot

2

Вы можете попробовать это:

$str = " Some text 11 have number 12 (11,12,13)"; 
$array = array(11 => 'eleven', 12 => 'twelve', 13 => 'thirteen'); 

foreach ($array as $key => $value) { 
    $str = preg_replace('/(\(|,)' . $key . '(\)|,)/', "$1" . $value . "$2", $str); 
} 

И когда вы var_dump($str):

string(53) " Some text 11 have number 12 (eleven,twelve,thirteen)" 
+1

Спасибо за явный код, но он не ограничивает поиск номерами между '(' и ','. Если вы добавите номер 1 в массив, он заменит 1 из 11. Regex должен диктовать, что предыдущий символ ' ('или', 'и следующий символ') 'или', '. – Googlebot

+0

Там вы идете @All, я обновил свое регулярное выражение, и теперь он должен работать, даже если вы добавляете более низкие цифры. –

2

Я хотел бы использовать preg_replace_callback. Затем вы можете использовать \(([\d\h,]+)\), который проверяет номера, горизонтальные пробелы или запятые внутри () и фиксирует все найденные значения. Затем функция использует str_replace для их замены.

$string = " Some text 11 have number 12 (11,12,13)"; 
$array = array(11 => 'eleven', 12 => 'twelve', 13 => 'thirteen'); 
echo preg_replace_callback('/\(([\d\h,]+)\)/', function ($matches) use ($array) { 
    return str_replace(array_keys($array), array_values($array), $matches[1]); 
}, $string); 

Демонстрация: https://eval.in/589888

+0

Я думаю, что есть только один Недостаток: вам нужно учесть отсутствующий массив. Хотя я также думаю, что вы можете использовать только 1 регулярное выражение для каждого номера в '(...)' отдельно, чтобы не использовать 'str_replace'. –

+0

Вы имеете в виду, ', 13 => 'тринадцать', 14, 15 => 'пятнадцать''? Да, я предположил, что массив всегда имеет парное число со словом. – chris85

+1

Я имел в виду [' (?: \ G (?! \ A) | \(),? \ K \ d + '] (https://regex101.com/r/aH1bT6/1) и проверяет наличие ключа с пустым ($ array [$ m [0]]). –

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