【问题标题】:PHP, preg_match: How to get strings in between two chars like curly braces with sub markers wraped in curly braces inside?PHP,preg_match:如何在两个字符之间获取字符串,如花括号,子标记包含在花括号中?
【发布时间】:2014-05-11 20:01:18
【问题描述】:

如果我有如下字符串:

$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}',
)

【问题讨论】:

    标签: php preg-match preg-match-all templating


    【解决方案1】:

    你需要使用递归模式,例如:

    $pattern = '~{((?>[^{}]++|(?R))*)}~';
    

    (?R) 代表所有模式(整个模式在其内部重复)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-11-30
      • 1970-01-01
      • 2023-01-29
      • 2021-05-25
      • 2010-09-29
      • 2011-07-17
      相关资源
      最近更新 更多