#php #regex
#php #регулярное выражение
Вопрос:
Мне может понадобиться небольшая помощь с этим регулярным выражением. Приведенное ниже регулярное выражение работает.
$regexgameid = '/{gameids([0-9][0-9][0-9][0-9][0-9])|([0-9][0-9][0-9][0-9][0-9])|([0-9][0-9][0-9][0-9][0-9])}/i';
preg_match_all($regexgameid, $articletext, $matchesgameid, PREG_SET_ORDER);
Пример целевого шорткода: {gameid 45735 76352 87262}
Количество идентификаторов игры может быть одним или тремя.
С моей логикой это было бы так:
$regexgameid = '/{gameids([0-9]{5}){1,3}}/i';
preg_match_all($regexgameid, $articletext, $matchesgameid, PREG_SET_ORDER);
Но это регулярное выражение выше не работает.
Чего я пытаюсь добиться, так это получить результаты из preg_match_all()
структуры массива, подобной этой:
Array
(
[0] => {gameid
[1] => 45735
[2] => 76352
[3] => 87262
[4] => }
)
чтобы я мог заменить весь {gameid 45735 76352 87262}
шорткод в тексте статьи информацией о 3 идентификаторах игр.
Комментарии:
1. Ваше регулярное выражение не допускает пробелов между числами.
{gameids([0-9]{5}s?){1,3}}
возможно2. Как насчет:
(?<game>gameid(?:.d{5}){1,3})
?
Ответ №1:
Вот демонстрация того, как использовать preg_replace_callback()
для замены тегов шорткода gameid в ваших (я полагаю, Joomla) статьях.
В своем вопросе вы указываете, что количество идентификаторов игры будет либо одним, либо тремя. По этой причине вам не следует использовать синтаксис {1,3}
квантора, потому что это означает «от одного до трех» вместо «один или три». Другими словами, для правильного шаблона потребуется, чтобы второй и третий идентификаторы существовали оба или ни один.
Сопоставляется весь короткий тег, поэтому все, что вам нужно сделать, это продиктовать перевод в параметре обратного вызова собственной функции.
Код: (Демо)
$articleText = <<<TEXT
Some article text
Triple id: {gameid 45735 76352 87262}.
Do not honor {gameid 12345 67890} because contains exactly 2 game ids!
unknown id: {gameid 66666} can't replace it!
Found single id: {gameid 76352}
finished the article
TEXT;
$gamesLookup = [
45735 => 'Pac-man',
76352 => 'Donkey Kong',
87262 => 'Rampage'
];
echo preg_replace_callback(
'~{gameid (d{5})(?: (d{5}) (d{5}))?}~',
function ($m) use ($gamesLookup) {
echo 'm = ' . var_export($m, true) . "n---n";
return 'Game Name(s): ' . strtr(implode(', ', array_slice($m, 1)), $gamesLookup);
},
$articleText
);
Вывод: (Я распечатываю массивы совпадений, чтобы вы могли видеть данные, к которым вам потребуется доступ)
m = array (
0 => '{gameid 45735 76352 87262}',
1 => '45735',
2 => '76352',
3 => '87262',
)
---
m = array (
0 => '{gameid 66666}',
1 => '66666',
)
---
m = array (
0 => '{gameid 76352}',
1 => '76352',
)
---
Some article text
Triple id: Game Name(s): Pac-man, Donkey Kong, Rampage.
Do not honor {gameid 12345 67890} because contains exactly 2 game ids!
unknown id: Game Name(s): 66666 can't replace it!
Found single id: Game Name(s): Donkey Kong
finished the article
Если вам просто нужен preg_match_all()
вызов, то достаточно того же шаблона…
Код: (Демо)
var_export(
preg_match_all('~{gameid (d{5})(?: (d{5}) (d{5}))?}~', $articleText, $m, PREG_SET_ORDER)
? $m
: []
);
Ответ №2:
Здесь есть несколько проблем. Во-первых, ваше исходное регулярное выражение неправильно использовало чередование: this (сокращено для краткости)…
/{gameids([0-9])|([0-9])}/
… на самом деле совпадает либо с on {gameid 5}
, либо только с on 5
, но никогда со всей группой. Скорее всего, это не то, что вы хотели.
Во-вторых, как правильно заметил @NigelRen, в вашем примере между последовательностью цифр есть пробел, но новый шаблон его не покрывает.
Вот один из подходов (предполагая, что вам действительно нужны целые идентификаторы игр, а не только цифры, сохраненные в $matchesgameid
):
$articletext = 'Here is some {gameid 55555 44444 33333} and here is some more {gameid 55555} and this is one more time {gameid 55555 33333}';
$regexgameid = '/{gameid(?:s[0-9]{5}){1,3}}/i';
preg_match_all($regexgameid, $articletext, $matchesgameid, PREG_SET_ORDER);
ДЕМОНСТРАЦИЯ. Группа переноса цифр здесь не фиксируется — как для экономии производительности, так и для того, чтобы не отвлекаться на результаты. Если идентификаторы GameID имеют противоречивые пробелы (у некоторых есть внутри, у некоторых нет), просто отметьте s
как необязательный с ?
помощью квантора:
'/{gameid(?:s?[0-9]{5}){1,3}}/i';