0

正規表現について学んでいて、PHP でテンプレート エンジンを書きたいと思っています。

次の「テンプレート」を検討してください。

<!DOCTYPE html>
<html lang="{{print("{hey}")}}" dir="{{$dir}}">
<head>
    <meta charset="{{$charset}}">
</head>
<body>
    {{$body}}
    {{}}
</body>
</html>

{{}} 以外を検索する正規表現を作成できました。

これが私の正規表現です:

{{[^}]+([^{])*}}

1つだけ問題があります。{リテラルをタグ}内で使用できるようにするにはどうすればよいですか?{{}}

見つかりません{{print("{hey}")}}

前もって感謝します。

4

4 に答える 4

2

これは、二重中かっこ内のコンテンツに一致するパターンです。

$pattern = <<<'LOD'
~
(?(DEFINE)
    (?<quoted>
        ' (?: [^'\\]+ | (?:\\.)+ )++ ' |
        " (?: [^"\\]+ | (?:\\.)+ )++ "
    )
    (?<nested>
        { (?: [^"'{}]+ | \g<quoted> | \g<nested> )*+ }
    )
)

{{
    (?<content>
        (?: 
            [^"'{}]+
          | \g<quoted>  
          | \g<nested>

        )*+
    )
}}
~xs
LOD;

コンパクトバージョン:

$pattern = '~{{((?>[^"\'{}]+|((["\'])(?:[^"\'\\\]+|(?:\\.)+|(?:(?!\3)["\'])+)++\3)|({(?:[^"\'{}]+|\g<2>|(?4))*+}))*+)}}~s';

コンテンツは最初のキャプチャ グループにありますが、名前付きキャプチャ'content'を詳細バージョンで使用できます。

このパターンが長い場合、エスケープされた引用符を含む、引用符で囲まれた部分の内部で必要なものがすべて許可され、多くの場合、単純な遅延量指定子よりも高速になります。ネストされた中括弧も許可されており、{{ doThat(){ doThis(){ }}}}問題なく記述できます。

引用符のサブパターンもこのように書くことができ、一重引用符と二重引用符で同じことを繰り返さないようにします (コンパクト バージョンで使用します)。

(["'])             # the quote type is captured (single or double)
(?:                # open a group (for the various alternatives)
    [^"'\\]+       # all characters that are not a quote or a backslash
  |                # OR
    (?:\\.)+       # escaped characters (with the \s modifier)
  |                #
    (?!\g{-1})["'] # a quote that is not the captured quote
)++                # repeat one or more times
\g{-1}             # the captured quote (-1 refers to the last capturing group)

注意: バックスラッシュ\\は nowdoc 構文で記述する必要がありますが\\\\\\\単一引用符で囲む必要があります。

詳細なパターンの説明:

パターンは次の 2 つの部分に分かれています。

  • 名前付きサブパターンを定義する定義
  • 全体のパターン自体

定義セクションは、メイン パターンで常に同じサブパターンを何度も繰り返すことを避けたり、より明確にしたりするのに役立ちます。このスペースで後で使用するサブパターンを定義できます。
(?(DEFINE)....)

このセクションには、2 つの名前付きサブパターンが含まれています。

  • quoted : 引用部分の説明を含む
  • nested : ネストされた中括弧部分を記述します

入れ子の詳細

(?<nested>           # open the named group "nested"
    {                # literal {
 ## what can contain curly brackets? ##
    (?>              # open an atomic* group
        [^"'{}]+     # all characters one or more times, except "'{}
      |              # OR
        \g<quoted>   # quoted content, to avoid curly brackets inside quoted parts
                     # (I call the subpattern I have defined before, instead of rewrite all)
      | \g<nested>   # OR curly parts. This is a recursion
    )*+              # repeat the atomic group zero or more times (possessive *)
    }                # literal }
)                    # close the named group

(*原子団所有量指定子に関する詳細情報)

しかし、これはすべて定義にすぎません。パターンは実際には次のように始まります。{{ 次に、名前付きのキャプチャ グループ ( content) を開き、内部にあるものを記述します (ここには新しいものはありません)。

私は修飾子に使用しxs. xパターンに自由にスペースを入れることができる冗長モードを有効にします (インデントに便利です)。sシングルラインモードです。このモードでは、ドットは改行に一致します (デフォルトでは一致しません)。サブパターンにドットがあるため、このモードを使用しますquoted

于 2013-08-03T00:52:08.307 に答える
2

「。」を使用できます。文字クラスの代わりに。ただし、貪欲でない量指定子を使用する必要があります。

\{\{(.+?)\}\}

量指定子「+?」必要最小限の文字数を消費することを意味します。

次の例を検討してください。

<table>
  <tr>
    <td>{{print("{first name}")}}</td><td>{{print("{last name}")}}</td>
  </tr>
</table>

{{貪欲な量指定子 (+ または *) を使用すると、パターンが一致する限り、最初の文字を見て、次に.+可能な限り多くの文字を消費するため、結果は 1 つしか得られません。

{{print("{first name}")}}</td><td>{{print("{last name}")}}

貪欲でないもの (+? または *?) を使用すると、2 つが別々の結果として得られます。

{{print("{first name}")}}
{{print("{last name}")}}
于 2013-08-02T23:40:01.120 に答える
0

私はそれを考え出した。方法を聞かないでください。

{{[^{}]*("[^"]*"\))?(}})

これは、ほとんど何でも一致します..例えば:

{{print("{{}}}{{{}}}}{}}{}{hey}}{}}}{}7")}}
于 2013-08-03T00:00:48.747 に答える
0

を使用して、正規表現の貪欲さを減らします{{(.*?)}}

于 2013-08-02T23:39:09.067 に答える