1

PHP(以及其他)将首先执行最深的函数,然后逐步退出。例如,

$text = strtoupper(str_replace('_', ' ', file_get_contents('file.txt')));

我正在为模板解析器做一些与上述示例非常相似的事情。它寻找标签

{@tag_name}

并将其替换为名称为 $tag_name的变量。再举一个例子:

$a = 'hello';
$b = ' world';
INPUT = 'This is my test {@a{@b}} string.';
OUTPUT (step 1) = 'This is my test {@a} world string.';
OUTPUT output = 'This is my test hello world string.';

我该怎么做呢?这有意义吗?如果没有,我可以尝试更好地解释。

4

4 回答 4

4

我不确定我是否理解您示例中的嵌套,因为该示例并未说明嵌套背后的目的。您的示例输入很容易成为

'This is my test {@a} {@b} string.'

在 str_replace 中使用数组将非常简单快速地处理这个问题。

$aVars = array('{@a}' => 'hello', '{@b}' => 'world');
$sString = 'This is my test {@a} {@b} string.';

echo str_replace(array_keys($aVars), array_values($aVars), $sString);

这给了我们

这是我的测试 hello world 字符串。

现在,对此的递归函数并不太难,尽管我不确定我是否理解它会有多大用处。这是一个工作示例:

function template($sText, $aVars) {
    if (preg_match_all('/({@([^{}]+)})/',
                       $sText, $aMatches, PREG_SET_ORDER)) {
        foreach($aMatches as $aMatch) {
            echo '<pre>' . print_r($aMatches, 1) . '</pre>';

            if (array_key_exists($aMatch[2], $aVars)) {
                // replace the guy inside
                $sText = str_replace($aMatch[1], $aVars[$aMatch[2]], $sText);

                // now run through the text again since we have new variables
                $sText = template($sText, $aVars);
            }
        }
    }

    return $sText;
}

该 print_r 将向您显示匹配项的外观,以便您可以按照该功能的步伐进行操作。现在让我们试一试...

$aVars = array('a' => 'hello', 'b' => 'world');
$sStringOne = 'This is my test {@a} {@b} string.';
$sStringTwo = 'This is my test {@a{@b}} string.';

echo template($sStringOne, $aVars) . '<br />';

第一个结果:

这是我的测试 hello world 字符串。

现在让我们试试字符串二

echo template($sStringTwo, $aVars) . '<br />';

第二个结果:

这是我的测试 {@aworld} 字符串。

这很可能就是您正在寻找的。显然,您需要一个aworld变量才能递归地工作......

$aVars = array('a' => '', 'b' => '2', 'a2' => 'hello world');

echo template($sStringTwo, $aVars) . '<br />';

和我们的结果。

这是我的测试 hello world 字符串。

只是为了一些递归的乐趣......

$aVars = array('a3' => 'hello world', 'b2' => '3', 'c1' => '2', 'd' => '1');
$sStringTre = 'This is my test {@a{@b{@c{@d}}}} string.';

echo template($sStringTre, $aVars) . '<br />';

这是我的测试 hello world 字符串。

不知道这是不是你要的...

于 2008-10-30T21:42:40.100 回答
1

这不是一项微不足道的任务。您需要手动解析字符串并进行自己的逻辑替换。没有神奇的功能或功能可以为您做到这一点。

我自己的模板引擎可以做到这一点(以及更多),只有核心(无模板宏)的重量为 600+ LOC

于 2008-10-30T20:18:52.610 回答
1

array_push使用堆栈 - 将每个打开的元素放在顶部,并array_pop在第一个结束标记处评估最顶部。

于 2008-10-30T20:30:41.540 回答
0

至少在给定的示例中,我不明白为什么 @b 令牌会嵌套在 @a 令牌中。两个人似乎没有什么需要。你想在 Perl 中做这样的事情吗?

$a = "b";
$b = "Hello World!";

print $$a;

输出将是“Hello World”

于 2008-10-30T20:20:07.770 回答