2

私がやろうとしているのは、ユーザーが挿入したテキスト (ブログ投稿など) 内の「関数」を特定の html ブロッ​​クに置き換え、「関数」内でオプション/値のペアを使用することです。クリア?いいえ?!そう思った:)ここに例があります:

Some text, can be long, may be short, a nice story, or just a comment.
{{function option1="value1" option2="value2"}}
And some more text!
{{function2 option1="value1" option2="value2"}}

テキストでは、その部分を置き換えて解析したいと考えています{{function ...}}。より具体的な例は次のとおりです。

{{youtube videokey="_VIDEOKEY_"}}

これは、YouTube 埋め込みコードに置き換える必要があります。

<iframe width="420" height="315" src="http://www.youtube.com/embed/_VIDEOKEY_" frameborder="0" allowfullscreen></iframe>

このために関数を使用したいpreg_replace_callback()ので、渡されたデータ/オプションに対していくつかの計算を行う余地があります。


問題: この ( ) のようにフォーマットされた部分文字列を取得して置き換えることができ、さらにオプション{{ ... }}/値のペアに一致させることもできます。

私は多くの式を試しましたが、最も近いと思うのは次のとおりです。

\{\{\w+([[:space:]]+(([0-9a-zA-Z]+)=\"([0-9a-zA-Z]+)\"))+\}\}

ご覧のとおり、一致させようとしています:

  1. {{および内の文字列}}
  2. 最初の部分は単語です
  3. 1 つ以上のオプション/値のペアが続きます。
    • 1 つ以上のスペース
    • 1 つ以上の文字または数字 (オプション名)
    • =サイン_
    • "(オプション値)で囲まれた 1 つ以上の文字または数字

例では、上記のテキストが一致します (preg_match_all を使用):

array(5) (
    0 => array(2) (
        0 => string(46) "{{function option1="value1" option2="value2"}}"
        1 => string(47) "{{function2 option1="value1" option2="value2"}}"
    )
    1 => array(2) (
        0 => string(17) " option2="value2""
        1 => string(17) " option2="value2""
    )
    2 => array(2) (
        0 => string(16) "option2="value2""
        1 => string(16) "option2="value2""
    )
    3 => array(2) (
        0 => string(7) "option2"
        1 => string(7) "option2"
    )
    4 => array(2) (
        0 => string(6) "value2"
        1 => string(6) "value2"
    )
)

もちろん、この正規表現で preg_replace_callback を使用すると、同じセットの一致を (1 次元配列で) 受け取ります。


私はこの解決策を持っていますが、好きではありません(正規表現の一致に正規表現が含まれているため、1つの式で実行できるはずだと思います):

$input = ... // see text above
$output = preg_replace_callback('@\{\{\w+([[:space:]]+(([0-9a-zA-Z]+)=\"([0-9a-zA-Z]+)\"))+\}\}@', 'my_replace_function', $input);

function my_replace_function($match) {
    preg_match_all('@([0-9a-zA-Z]+)=\"([0-9a-zA-Z]+)\"@', $match[0], $matches);
    // do something with the $matches
}

最後の一致だけでなく、すべてのオプション/値のペアを含む配列をコールバック関数に配信し、そのデータを使用して文字列を解析することは可能ですか? もしそうなら、私を正しい方向に向けてもらえますか?

基本的に問題は次のとおりです: マッチで反復的なサブパターンを分離できますか?


---編集--- 上記で提案された解決策 (「関数」ブロック全体をキャプチャし、一致した文字列内のオプションと値のペアを一致させる) は、実際にはこのパズルの解決策です。詳細については、以下の @m.buettner の回答 (受け入れられたもの) を参照してください。

4

1 に答える 1

2

できません。申し訳ありませんが、それはとても簡単です。ほとんどの正規表現エンジンは、単一のキャプチャ グループによる複数の値のキャプチャをサポートしていません。つまり、ほとんどの正規表現エンジンは、限られた固定数のキャプチャしかサポートしていません。.NET はここでの大きな例外です。しかし、あなたは PCRE を使用しています - そして、PCRE は常に各グループの最後のキャプチャを返します (ここを参照してください、公式の引用は保留中ですが、「PCRE 繰り返しキャプチャ グループ」をグーグルで検索すると、すべての情報源が同意します)。グループの数は、パターン内の括弧の数によって固定されます。繰り返しのキャプチャを繰り返しの一致に変換する回避策が考えられる場合がありますが、それはあなたの場合にも当てはまらないと思います。

したがって、あなたのソリューションは本当に正しい方法です。ブロック全体を照合し{{...}}、コールバック内のキーと値のペアを個別に解析します。

于 2012-12-03T17:11:09.473 に答える