如果我有一个像这样的字符串:
$str = "Some {translate:text} with some {if:{isCool}?{translate:cool}|{translate:uncool}} features";
…我希望得到以下结果:
array (
0 => 'translate:text',
1 => 'if:{isCool}?{translate:cool}|{translate:uncool}',
)
我已经有这个函数,但我相信它可以简化它与preg_match(_all)?
define('STR_START','{');
define('STR_END','}');
function getMarkers($str, &$arr = array()) {
if(strpos($str,STR_START)) {
list($trash,$str) = explode(STR_START,$str, 2);
unset($trash);
$startPos = 0;
$endPos = 0;
do {
$strStartPos = strpos($str,STR_START,$startPos);
$strEndPos = strpos($str,STR_END,$endPos);
$startPos = $strStartPos + 1;
$endPos = $strEndPos + 1;
} while($strStartPos !== false && $strStartPos < $strEndPos);
$arr[] = substr($str,0,$strEndPos);
getMarkers(substr($str,$strEndPos+1),$arr);
}
return $arr;
}
我已经尝试了以下方法,但它对子标记的效果不太好。
preg_match_all('/{(.*?)}/',"Some {translate:text} with some {if:{isCool}?{translate:cool}|{translate:uncool}} features", $matches);
var_export($matches[1]);
array (
0 => 'translate:text',
1 => 'if:{isCool',
2 => 'translate:cool',
3 => 'translate:uncool',
)
是否有可能调整上述模式以获得正确的结果?
array (
0 => 'translate:text',
1 => 'if:{isCool}?{translate:cool}|{translate:uncool}',
)
您需要使用递归模式,例如:
$pattern = '~{((?>[^{}]++|(?R))*)}~';
其中(?R)
代表所有模式(整个模式在自身内部重复)