0

最大3つの要素を含む2つの文字列があります。

1) anychar[price]{alphanum} e.g. a1\')[=00.00]{a1234}
2) anychar:anychar{alphanum} e.g. a1\'):a2\'){a1234}

...ただし、{}要素はオプションであり、常に存在するとは限りません。私は(それぞれ)次のパターンを書きました:

1)/(.+)\[(.+)\]\{*(\w+)*\}*/-期待どおりに機能します

2)/(.+)\:(.+)\{*(\w+)*\}*/-{}要素が削除された場合は正常に機能しますが、削除された場合は機能しません。

2の結果の配列は次のとおりです。

( [0] => a1\'):a2\'){a123} [1] => a1\') [2] => a2\'){a123} )

上記のいくつかの異なる順列を試しましたが、サイコロはありません。何か案は?

4

1 に答える 1

1

最初に、{、} および (\w+) の後の * を削除する必要があります。

'/(.+)\:(.+)\{(\w+)\}/'

与える

array(4) {
  [0]=>
  string(18) "a1\'):a2\'){a1234}"
  [1]=>
  string(5) "a1\')"
  [2]=>
  string(5) "a2\')"
  [3]=>
  string(5) "a1234"
}

* は 0、1、または複数を意味し、PCRE は可能な限り最速のルートを見つけようとします。そのため、3 番目の部分全体を (どこでも * を使用して) オプションにすると、2 番目のグループにすべてを含めてスキップするのが最も速いルートになります。 3 つ目は、それが原因でコードが機能しませんでした。

3 番目の部分がオプションであるという事実に対処するために、肯定的な先読みを使用する必要があります。2 番目のグループでは、その後の別の正規表現と一致する場合にのみ pcre にそれを選択するように要求します。最終的な正規表現は次のとおりです。

'/(.+)\:(.+(?=(?:(?<=[^}])$|\{(\w+)\})))/'

私が変更したのは次のとおりです。

  • 2 番目のグループ内で、(?=regex) の形式で肯定的な先読みを追加しました。前述のとおり、これは一致する必要があることを意味します。先読みはデフォルトでは選択的ではありません。つまり、最終結果にエントリが作成されないか、返されません。

  • その先読みの中で、2 つのケースを作成しました。つまり、一致するためには、2 番目のグループの .+ が先読みのいずれかのケースと一致する必要があります。

  • 最初のケースは非常に基本的なもので、前に } が付いていない文字列の末尾を意味します。これは、3 番目の部分がない場合に文字列と一致します。

  • 2 番目のケースで 3 番目のグループを選択する場合は、選択可能にして、存在する場合は結果に返されるようにします。

于 2011-05-27T09:28:29.513 に答える