0

次のコードを使用します。

$target = 'NAME FUNC LPAREN P COMMA P COMMA P RPAREN';
//$target = 'NAME FUNC LPAREN P RPAREN';
//$target = 'NAME FUNC LPAREN RPAREN';
$pattern = '/(?P<ruleName>NAME )?(?P<funcName>FUNC )?(?:(?<=LPAREN)(?: (?P<arg1>P))|(?P<args>P)(?=(?: RPAREN)|(?: COMMA)))/';

preg_match_all($pattern,$target,$matches,PREG_OFFSET_CAPTURE|PREG_PATTERN_ORDER);

$target 内の NAME、FUNC、および各 P の位置を取得する必要があります (つまり、PREG_OFFSET_CAPTURE)。このパターンは Ps に対して機能しますが、名前付きグループ「ruleName」または「funcName」のいずれとも一致しません。

私は何が欠けていますか?

ありがとう。

4

1 に答える 1

1

理由が分かった気がします。

  1. 名前付き後方参照はオプションです。
  2. それらが一致する場合 (そして最初の試行で一致する場合)、正規表現エンジンは "LPAREN" の左側に立っています。
  3. 正規表現エンジンが一致しようとする次のトークンは、スペース文字です。これは、後読み式(?<=LPAREN)が文字列内の文字を消費しないためです。
  4. Lがあるからスペースが合わない
  5. 正規表現エンジンは、2. からのオプションの一致を破棄し、次のスペースが見つかるまで続けます。
  6. 一致し、それ以降も一致し続け、すべての をキャプチャしますP。しかし、これを機能させるには、名前付きグループを放棄する必要がありました。

なぜ後読みが必要なのかわかりません。どうですか

/(?P<ruleName>NAME )?(?P<funcName>FUNC )?(?:LPAREN )(?:(?P<arg1>P))|(?P<args>P)(?=(?: RPAREN)|(?: COMMA))/
于 2009-11-26T19:58:23.477 に答える