2017-12-11 12 views
1

このタスクはかなり明確です。入力では、おそらくという名前のサブパターンを含む変数正規表現パターンを、持っている、との出力に、私たちはサブパターンの名前の配列を取得する必要があります。パターン内のpreg_match_allサブパターン名

function get_subpattern_names($any_input_pattern) { 
    // What pattern to use here? 
    $pattern_to_get_names = '/.../'; 

    preg_match_all($pattern_to_get_names, $any_input_pattern, $matches); 

    return $matches; 
} 

そこで質問が関数に$pattern_to_get_namesとして使用するものです上記?例えば

get_subpattern_names('/(?P<name>\w+): (?P<digit>\d+)/'); 

が返さなければならない:

array('name', 'digit'); 

P.S:PCRE documentationサブパターン名によるとは、最大32個の文字の英数字および下線で構成されています。

入力パターンを制御しないので、名前付けの考えられるすべての構文を考慮する必要があります。 PHP documentationによれば、それらは:
(?P<name>pattern),(?<name>pattern)および(?'name'pattern)である。

ネストされたサブパターンも考慮する必要があります(例:
(?<name1>.*(?<name2>pattern).*))。

名前の重複をカウントしたり、出現順序を保持したり、数字、非キャプチャなどのサブパターンを取得する必要はありません。名前のリストだけが存在する場合。

+0

https://ideone.com/UoLUYBとhttps://regex101.com/r/Rfx389/1 –

答えて

3

あなたは

"~(?<!\\\\)(?:\\\\{2})*\(\?(?|P?<([_A-Za-z]\w{0,31})>|'([_A-Za-z]\w{0,31})')~" 

を使用して、すべての有効な名前付きキャプチャグループ名のリストを取得することがregexonline PHP demoを参照してください。

ポイントは、その後のいずれかP<または<と続く?と続くエスケープ(と一致するようにされ、次いで>又は'グループ名のパターンで追跡し、次いで'で終わるグループ名パターンを有します。

$rx = "~(?<!\\\\)(?:\\\\{2})*\(\?(?|P?<([_A-Za-z]\w{0,31})>|'([_A-Za-z]\w{0,31})')~"; 
$s = "(?P<name>\w+): (?<name2>\w+): (?'digit'\d+)"; 
preg_match_all($rx, $s, $res); 
print_r($res[1]); 

利回り

Array 
(
    [0] => name 
    [1] => name2 
    [2] => digit 
) 

パターンが

  • (?<!\\)を詳述しない - いずれかを許可する0+ダブルバックスラッシュ( - 現在の場所
  • (?:\\\\)*のすぐ左に何\の前にバックスラッシュをエスケープしました)
  • \(から(
  • \?から?
  • (?|P?<([_A-Za-z]\w{0,31})>|'([_A-Za-z]\w{0,31})') - 分岐リセット群:
    • P?<([_A-Za-z]\w{0,31})> - 任意P<_またはASCII文字、0〜31ワード文字(数字/文字/ _)(グループ1に取り込まれる)、>
    • | - または
    • '([_A-Za-z]\w{0,31})' - '_または(また、グループ1に取り込ま)ASCII文字、0〜31のワード文字(数字/文字/ _)、次いで'

グループ名パターンすべてがグループ1に取り込まれたら、$res[1]を取得するだけです。

1

ウィクターのソリューションはかなり徹底しているようですが、ここで私が思いついたのはこれです。

print_r(get_subpattern_names('/(?P<name>\w+): (?P<digit>\d+)/')); 

function get_subpattern_names($input_pattern){ 
    preg_match_all('/\?P\<(.+?)\>/i', $input_pattern, $matches); 
    return $matches[1]; 
} 

これはほとんどの場合有効です。もっと重要なことは、これははるかに読みやすく、自明であることです。

基本的には、?P<を検索してから、(.+?)を探します。これは角括弧の間にあるもののnon-greedyバージョンに変換されます。この関数は、$matches配列内の最初のオフセットを返します。この配列は、最初にマッチした括弧のセットを示します。

+0

を参照してください申し訳ありませんが、あなたの答えは考えられる他の構文を考慮していません。 –

関連する問題