1

次のように入力できるテンプレートシステムを作成しています。

<t:category:item:parameter1:parameter2...>

そして、それをファイルのテキストに置き換えます。オプションのパラメータは、置換文字列に%1, %2...として配置されます。

これまでのところ、私はこれを持っています:

$data = preg_replace_callback("/<t:([^:]+):([^>]+)>/",function($m) use (&$userdata) {
    static $fcache = Array();
    $parse = function($file) use (&$fcache,&$lang) {
        // parse the file if it's a new one. False indicates success, otherwise error message is returned
        if( !isset($fcache[$file])) {
            if( !file_exists("text/".$lang."/".$file.".html")) $lang = "en";
            if( !file_exists("text/".$lang."/".$file.".html")) return "<div class=\"alert\">ERROR: File ".$file." not found.</div>";
            $k = "";
            foreach(file("text/".$lang."/".$file.".html") as $l) {
                if( substr($l,0,1) == "|") $k = rtrim(substr($l,1));
                else $fcache[$file][$k] .= $l;
            }
        }
        return false;
    };
    $lang = $userdata && $userdata['language'] ? $userdata['language'] : "uk";
    list(,$file,$d) = $m;
    $params = explode(":",$d);
    $section = array_shift($params);
    if( $e = $parse($file)) return $e;
    if( !$fcache[$file][$section]) {
        $lang = "uk";
        if( $e = $parse($file)) return $e;
    }
    return preg_replace_callback("/%(\d+)/",function($i) use ($params) {
        return htmlspecialchars_decode($params[$i[1]-1]);
    },trim($fcache[$file][$section]));
},$data);

テキスト ファイルの形式は次のとおりです。

|key
replacement text
|otherkey
more text %1

とにかく、要点を言えば: パラメータの 1 つ自体が置換文字列である場合はどうなるでしょうか。たとえば、「すぐに彼に会いに来てください!」のような文字列が必要な場合はどうでしょうか。- 私はそれを次のようにしたいと思います:

<t:person:visit:<t:grammar:pronoun_object_m>>

ファイルには次のものが含まれます。

|visit
Come and visit %1 soon!

|pronoun_object_m
him

ただし、現在の関数はパラメーターをリテラルとして受け取り、フレーズの最後に<t:grammar:pronoun_object_m追加のものが表示されます。>

<t:grammar:pronoun_object_m にすぐにアクセスしてください!>

実際には次のように表示されます。

来て、訪問してください

HTMLタグのように見える解析されていない置換のため...

再帰的な正規表現が必要だと確信していますが、それらがどのように機能するかについては非常に混乱しています。このような埋め込みパラメータを許可するために正規表現を「再帰」する方法を誰か説明してもらえますか?

4

1 に答える 1

2

再帰的なソリューションの問題は、preg_replace. それらは主に を対象としていpreg_matchます。その理由は、再帰内で再利用されるパターンの最後の (最も内側の) キャプチャにしかアクセスできないためです。したがって、ここでもpreg_replace_callbackあまり役に立ちません。

ここに別の可能性があります:

<t:person:visit:<t:grammar:pronoun_object_m>>、言及した出力が得られる理由は、正規表現がこれと一致するためです。

<t:person:visit:<t:grammar:pronoun_object_m>

(プレースホルダー内で禁止しているため、これ以上進むことはできません>。)

これを回避するにはいくつかの方法があります。手始めに、プレースホルダー内で<( だけでなく)を禁止することもできます。>

"/<t:([^:]+):([^<>]+)>/"

これで、パターンは常に最も内側のプレースホルダーのみを見つけます。preg_replace_callbackしたがって、置換が行われなくなるまで繰り返し呼び出すことができます。これを見つける方法は?オプションの 4 番目と 5 番目のパラメーターを追加します。

do
{
    preg_replace_callback("/<t:([^:]+):([^<>]+)>/", $function, $data, -1, $count);
} while($count);

また、(読みやすくするために) 関数の外でコールバックを定義することをお勧めしますpreg_replace_callback

于 2012-10-16T21:00:03.957 に答える