3

PHP でパーサーを開発しています。関数を含む文字列を検証するには、機能的な正規表現が必要です。

理解するために、関数を使用preg_replace_callbackcreate_functionて実行し、文字列の値を再帰的に置き換えることを検討します。

文字列の例:15 + func1 ("gis", 22, func (55), 87) + 95 + func2 () + 35

func1正規表現は、すべての関数を結合して結合できる必要がありますfunc 2。正規表現は関数としてのみ(([^ ()])+([ ]?)*\(.*\))*出力しています。func1 ("gis", 22, func (55), 87) + 95 + func2 ()「95」はどの機能にも属さないので間違っています。正規表現は、func1 内のロールなどの関数も処理できる必要があります。

どんな助けにも感謝します。

4

2 に答える 2

1

これを試すことができます:

$subject = '15 + func1 ("gis", 22, func (55), 87) + 95 + func2 () + 35';

$pattern = <<<'LOD'
~
 #definitions:

 (?(DEFINE)(?<int>     [0-9]++        ))
 (?(DEFINE)(?<str>     "[^"]++"       ))

 (?(DEFINE)(?<f_name>  \b[a-z]\w*+\b  ))
 (?(DEFINE)(?<sep>     ,\h            ))

 #pattern:

 (?=
     (
        (?<func>\g<f_name>) \s*+
        \( 
           (?<args>
             (?> (?> \g<int> | \g<str> | (?-3) ) \g<sep>?+ )*
           )
        \) 
     )
 )
~x
LOD;

preg_match_all($pattern, $subject, $matches);

print_r($matches['func']);
print_r($matches['args']);

アイデアは、再帰を使用して関数内の関数を一致させ、すべてのパターンを先読み内に配置して、重複するすべての引数をキャプチャすることです。

(?-3)パターンの最初のグループである左側の 3 番目のキャプチャ グループを参照するために再帰を使用することに注意してください(?1)。ただし、このパターンをサブパターンとして使用する場合は、相対参照が役立ちます。

(?(DEFINE)..)コメント モード(x 修飾子)と組み合わせると、非常に編集しやすく、データ型やパーサーが遭遇する可能性のあるその他の要素を追加または編集できるため、便利です。たとえば、一重引用符の間の文字列を許可する場合は、次の<str>ようにサブパターンを変更できます。

(?(DEFINE)(?<str>     "[^"]++" | '[^']++'    ))

または、これをより寛容にする(引用符のエスケープを許可する)

(?(DEFINE)(?<str>     "(?>[^"]++|(?<=\\)")++" | '(?>[^']++|(?<=\\)')++'  ))
于 2013-06-15T20:31:33.597 に答える