PHP – помощь с моей рекурсивной функцией на основе REGEX

Я извлекаю строку из API википедии, которая изначально выглядит так: текст ссылки . Я хочу удалить все {{…}} и все между ними (может быть любой текст). Для этого я подумал об использовании рекурсивной функции с « preg_match », « preg_replace ». что-то вроде:

 function drop_brax($text) { if(preg_match('/{{(.)*}}/',$text)) return drop_brax(preg_replace('/{{(.)*}}/','',$text)); return $text; } 

Эта функция не будет работать из-за такой ситуации:

{{Мне нравится mocachino {{но мне также нравятся бананы}} и frutis}}

это отделит все, что происходит между первым вступлением как {{и}} (и оставить «и frutis}}»). Как я могу сделать это правильно? (сохраняя при этом хорошую рекурсивную форму).

Попробуйте что-то вроде этого:

 $text = '...{{aa{{bb}}cc}}...{{aa{{bb{{cc}}bb{{cc}}bb}}dd}}...'; preg_match_all('/\{\{(?:[^{}]|(?R))*}}/', $text, $matches); print_r($matches); 

вывод:

 Array ( [0] => Array ( [0] => {{aa{{bb}}cc}} [1] => {{aa{{bb{{cc}}bb{{cc}}bb}}dd}} ) ) 

И короткое объяснение:

 \{\{ # match two opening brackets (?: # start non-capturing group 1 [^{}] # match any character except '{' and '}' | # OR (?R) # recursively call the entire pattern: \{\{(?:[^{}]|(?R))*}} ) # end non-capturing group 1 * # repeat non-capturing group 1 zero or more times }} # match two closing brackets 

для полного рекурсивного анализа вам понадобится парсер:

 function drop_brax($str) { $buffer = NULL; $depth = 0; $strlen_str = strlen($str); for($i = 0; $i < $strlen_str; $i++) { $char = $str[$i]; switch ($char) { case '{': $depth++; break; case '}': $depth--; break; default: $buffer .= ($depth === 0) ? $char : NULL; } } return $buffer; } $str = 'some text {{ I like mocachino {{ but I also like banana}} and frutis }} some text'; $str = drop_brax($str); echo $str; 

вывод:

 some text some text