Я знаю, что синтаксический анализ вложенных строк или HTML лучше выполняется с помощью реального анализатора, но в моем случае у меня есть простые шаблоны и вы хотите извлечь содержимое заголовка Wiki параметр 'title' из шаблона. Мне потребовалось некоторое время, чтобы добиться этого, но благодаря инструменту regex Lars Olav Torvik (http://regex.larsolavtorvik.com/), и этот форум пользователя здесь я получил. Может быть, кто-то сочтет это полезным. (Мы все хотим внести свой вклад, он, не так ли? ;-) Следующий код, аннотированный комментариями, делает трюк. Я должен был сделать это, взглянув вокруг утверждений, чтобы не смешивать два шаблона, и в одном из них нет названия.Анализ сбалансированных вложенных шаблонов вики и извлечение содержимого строки одной строки с помощью regexp
Я еще не уверен в двух вопросах в комментариях к регулярному выражению - см. (?# Questions: …)
-if Я понял рекурсивную часть на (?R)
. Является ли он, что он получает свой контент для проверки с самого внешнего определенного уровня, то есть второй строки регулярного выражения \{\{
и последней строки регулярного выражения \}\}
? Правильно ли это? И в чем разница между ++
и +
перед альтернативой (?R)
стенд работает одинаково, поэтому кажется, что его тестировали.
В origninal шаблоны вики на странице (самый простой):
$wikiTemplate = " {{Templ1 | title = (1. template) title }} {{Templ2 | any parameter = something {{template}} }} {{Templ1 | title = (3. template) title }} ";
Замена:
$wikiTemplate = preg_replace( array( // tag all templates with START … END and add a TITLE-placeholder before // and take care of balanced {{ … }} recursiveness "@(?s) (?# switch to dotall match, i.e. also linebreaks) \{\{ (?# find two {{) (?: (?# group 1 as a non-backreferenced match ) (?: (?# group 2 as a non-backreferenced match ) (?! (?# in group 1 anything but not {{ or }}) \{\{ | (?# or) \}\} ) . )++ (?# Question: what is the differenc between ++ and + here?) | (?# or) (?R) (?# is it recursive of what is defined in the outermost, i.e. 2nd regexp line with \{\{ and last line with \}\} Question: is that here understood correctly?) ) * (?# zero or many times of the inner regexp defintions) \}\} (?# find two }}) @x",// x-extended → ignore white space in the pattern // replace TITLE by single line content of title parameter "@ (?<=TITLE) (?# TITLE must preceed the following linebreak but is not backreferenced within \\0, i.e. the whole returned match) ([\n\r]+) (?#linebr in 1 may also described as . because of s-modifier dotall) (?: (?# start non-backreferenced match) . (?# any character but not followed by START) (?!START) )+ (?# multiple times) (?: (?# start non-backreferenced match) \|\s*title\s*=\s* (?#find the parameter '| title = ') ) ([^\r\n]+) (?#get title now to \\2 but exclude the line break. Note it is buggy when there is no line break) (?: (?# start non-backreferenced match) . (?# any character but not followed by END) (?!END) ) + (?# multiple times) . (?# any single character, e.g. the last because as all stuff before captures anything not followed by END) (?:END) (?#a not backreferenced END) @msx", // m-multiline, s-dotall match also linebreaks, // x-extended → ignore white space in the pattern ), array( "TITLE\nSTART\\0END", // \0 is the whole returned match, i.e. the template # replace the TITLE to TITLEtitle contentTITLE… "\\2TITLE\\0", ), $wikiTemplate ); print_r($wikiTemplate);
Выход затем с названиями меченых по названию над каждым шаблоном, но только в случае наличия названия:
TITLE(1. template) titleTITLE START{{Templ1 | title = (1. template) title }}END TITLE START{{Templ2 | any parameter = something {{template}} }}END TITLE(3. template) titleTITLE START{{Templ1 | title = (3. template) title }}END
Любой внутри для моих вопросов, связанных с регулярным выражением понимания, или некоторые улучшения? Спасибо, Андреас.
Только теперь я понимаю, сколько лет этот вопрос ... –
Не имеет значения, сколько лет вопрос, спасибо в любом случае ;-) –