4
preg_replace("/\[b\](.*)\[\/b\]/Usi", "<strong>$1</strong>", "Some text here... [b][b]Hello, [b]PHP![/b][/b][/b] ... [b]and here[/b]");

戻り値

Some text here... <strong>[b]Hello, [b]PHP!</strong>[/b][/b] ... <strong>and here</strong>

しかし、すべての [b]...[/b] タグを置き換える必要があります。私の場合、なぜこれが起こらないのですか?

4

3 に答える 3

4

はい、要素がネストされている場合は、マルチパス アプローチが必要です。これは、次の 2 つの方法のいずれかで実行できます。以下は、各手法を説明する完全にコメントされた正規表現を含む 2 つのテスト済みスクリプトです。

1. 裏返しに交換します。

<?php // test.php Rev:20121016_0900
$re = '% # Match innermost [b]...[/b] structure.
    \[b\]              # Literal start tag.
    (                  # $1: Element contents.
      # Use Friedls "Unrolling-the-Loop" technique:
      #   Begin: {normal* (special normal*)*} construct.
      [^[]*            # {normal*} Zero or more non-"[".
      (?:              # Begin {(special normal*)*}.
        \[             # {special} Tag open literal char,
        (?!/?b\])      # but only if NOT [b] or [/b].
        [^[]*          # More {normal*}.
      )*               # Finish {(special normal*)*}.
    )                  # $1: Element contents.
    \[/b\]             # Literal end tag.
    %x';
printf("Replace matching tags from the inside out:\n");
$text = file_get_contents('testdata.txt');
$i=0; // Keep track of iteration number.
printf("i[%d]=%s", $i++, $text);
while(preg_match($re, $text)){
    $text = preg_replace($re, '<strong>$1</strong>', $text);
    printf("i[%d]=%s", $i++, $text);
}
?>

出力:

'''
Replace matching tags from the inside out:
i[0]=Some text here... [b][b]Hello, [b]PHP![/b][/b][/b] ... [b]and here[/b]
i[1]=Some text here... [b][b]Hello, <strong>PHP!</strong>[/b][/b] ... <strong>and here</strong>
i[2]=Some text here... [b]<strong>Hello, <strong>PHP!</strong></strong>[/b] ... <strong>and here</strong>
i[3]=Some text here... <strong><strong>Hello, <strong>PHP!</strong></strong></strong> ... <strong>and here</strong>
'''

2. 外側から次のように交換します。

<?php // test.php Rev:20121016_0901
$re = '% # Match outermost [b]...[/b] structure.
    \[b\]              # Literal start tag.
    (                  # $1: Element contents.
      (?:              # Zero or more contents alternatives.
        [^[]*          # Either non-[b]...[/b] stuff...
        (?:            # Begin {(special normal*)*}.
          \[           # {special} Tag open literal char,
          (?!/?b\])    # but only if NOT [b] or [/b].
          [^[]*        # More {normal*}.
        )*             # Finish {(special normal*)*}.
      | (?R)           # Or a nested [b]...[/b] structure.
      )*               # Zero or more contents alternatives.
    )                  # $1: Element contents.
    \[/b\]             # Literal end tag.
    %x';
printf("Replace matching tags from the outside in:\n");
$text = file_get_contents('testdata.txt');
$i=0; // Keep track of iteration number.
printf("i[%d]=%s", $i++, $text);
while(preg_match($re, $text)){
    $text = preg_replace($re, '<strong>$1</strong>', $text);
    printf("i[%d]=%s", $i++, $text);
}
?>

出力:

'''
Replace matching tags from the outside in:
i[0]=Some text here... [b][b]Hello, [b]PHP![/b][/b][/b] ... [b]and here[/b]
i[1]=Some text here... <strong>[b]Hello, [b]PHP![/b][/b]</strong> ... <strong>and here</strong>
i[2]=Some text here... <strong><strong>Hello, [b]PHP![/b]</strong></strong> ... <strong>and here</strong>
i[3]=Some text here... <strong><strong>Hello, <strong>PHP!</strong></strong></strong> ... <strong>and here</strong>
'''

(?R)2 番目のアプローチで使用される再帰式に注意してください。

于 2012-10-16T16:09:56.553 に答える
1

うまくいかない理由: 最初の [b] をキャッチしてから、次の [/b] に移動し、その間にあるものは何も変更せずに残します。つまり、外側の [b] タグを変更しますが、内側にネストされたタグは変更しません。

@meza へのコメントは、疑似タグをペアで置き換えるか、そのままにしておくことを示唆しています。これを行う最善の方法は、このように複数のパスを使用することです

$markup = "Some text here... [b][b]Hello, [b]PHP![/b][/b][/b] ... [b]and here[/b]";
$count = 0;
do {
    $markup = preg_replace("/\[b\](.*?)\[\/b\]/usi", "<strong>$1</strong>", $markup, -1, $count );
} while ( $count > 0 );

print $markup;

1行の正規表現でできるかどうかさえわかりませんが、できたとしても、かなり複雑で維持が難しいでしょう。

于 2012-10-16T10:40:10.190 に答える
0

この特定のケースに正規表現を使用するのはなぜですか?すべての[b]をstrongに、すべての[/b]を/strongに置き換える単純な文字列で解決できます。

于 2012-10-16T10:13:47.830 に答える