4

私が取り組んでいる文字列は次のようになります。

abc {def ghi {jkl mno} pqr stv} xy z

また、図の括弧に含まれているものをタグに入れる必要があるので、次のようになります。

abc <tag>def ghi <tag>jkl mno</tag> pqr stv</tag> xy z

私はもう試した

'#(?<!\pL)\{  ( ([^{}]+) | (?R) )*  \}(?!\pL)#xu'

しかし、私が得るのはただ<tag>xy z</tag>です。助けてください、私は何が間違っているのですか?

4

2 に答える 2

5

ネストされた構造は定義上、正規表現には複雑すぎます (はい、PCRE は再帰をサポートしていますが、この置換の問題には役立ちません)。可能なオプションが 2 つあります (とにかく正規表現を使用します)。まず、開き括弧を開きタグに置き換え、閉じタグも同じように置き換えることができます。ただし、これは一致しないブラケットも変換します。

$str = preg_replace('/\{/', '<tag>', $str);
$str = preg_replace('/\}/', '</tag>', $str);

もう 1 つのオプションは、一致する{andのみを置き換える}ことですが、1 回の呼び出しでpreg_replace複数のネストされたレベルを置き換えることができないため、繰り返し実行する必要があります。

do
{
    $str = preg_replace('/\{([^{]*?)\}/', '<tag>$1</tag>', $str, -1, $count);
}
while ($count > 0)

編集: PCRE は再帰をサポートしていますが、(?R)これはおそらく置換には役立ちません。その理由は、キャプチャ グループが繰り返される場合、その参照には最後のキャプチャのみが含まれるためです (つまり、 で一致/(a|b)+/する場合aaaab$1が含まれますb)。これは再帰でも同じだと思います。そのため、再帰内のキャプチャ グループの最後の一致であるため、最も内側の一致のみを置き換えることができます。{同様に、これらをキャプチャして再帰して置換しようとすることはできません}。これは、それらが任意の回数一致する可能性があり、最後の一致のみが置換されるためです。

複数の一致が重複することは決してないため、正しいネストされた構文を一致させてから、最も内側または最も外側の一致するブラケットを置き換えても、(1 回のpreg_replace呼び出しで) どちらも役に立ちません (したがって、3 つのネストされたブラケットが見つかった場合、内側の 2 つのブラケット自体は無視されます)。さらにマッチ)。

于 2012-10-12T17:31:10.993 に答える
3

2つのステップはどうですか:

s!{!<tag>!g;
s!}!</tag>!g;

(perl 形式。必要に応じて自分の形式に変換してください)

または多分これ:

1 while s!{([^{}]*)}!<tag>$1</tag>!g;

于 2012-10-12T17:23:10.643 に答える