[概要]
こちらの質問のベストアンサーを理解しようとしています。
意味としてどうしても解釈できない部分があり、教えて下さい。
[分からないコード]
PHP
1 /^(?=[^「」\p{C}\p{L}\p{N}]*+[\p{L}\p{N}])$/
[自分(なり)の解釈]
カッコと制御文字等とアルファベットと数字でない文字が
1文字以上続き、かつ、
アルファベット数字が後ろに続いてる文字列の前にある候補
↓
しかしこの解釈では本質的な意味をなさない
[分からない点]
- 先頭に先読みを置く意味
- 否定候補と候補の両方に\p{L}\p{N}が含まれている
(この先読みの意味する所全般が理解できない)
- 候補の間にあるゼロ回以上、1回以上の記号が連続している意味
この該当部分のところのコメントに「\p{L}\p{N} を最低1個は含む」とありますが
それならば「(?=[\p{L}\p{N}]+?)」ではだめなのでしょうか。
[試してみたこと]
① Unicode 文字プロパティの確認
C:コントロール文字や非可視整形用文字、サロゲート等
L:アルファベット(Ll、 Lm、Lo、Lt および Lu を含む)
N:数字
② 該当部分を削除してその部分の働きを見る
(2箇所の該当部分を削除して実行する)
PHP
1function parse(string $input): array{ 2 static $pattern = <<<'EOD' 3/ 4 # 先頭 5 ^ 6 # name 部分 7 (?<name> 8 # \p{L}\p{N} を最低1個は含む 9 # <<<削除>>> 10 # カッコと制御文字以外の繰り返し 11 [^「」\p{C}]++ 12 )? 13 # カッコ+空白だけのコメントの場合は読み飛ばす条件分岐 14 (?: 15 # empty_comment 部分 16 (?<empty_comment> 17 「 18 # カッコの中身 19 (?: 20 # empty_comment の再帰 21 (?&empty_comment) 22 )*+ 23 」 24 ) 25 # empty_comment がマッチしたらそこまでをすべて読み飛ばす 26 (*SKIP)(*FAIL) 27 | 28 # comment 部分 29 (?<comment> 30 「 31 # カッコの中身 32 (?: 33 # \p{L}\p{N} を最低1個は含む 34 # <<<削除>>> 35 # カッコと制御文字以外の繰り返し 36 [^「」\p{C}]*+ 37 38 # または 39 | 40 # comment の再帰 41 (?&comment) 42 )*+ 43 」 44 )? 45 ) 46 # 末尾 47 $ 48 /ux 49EOD; 50 51 preg_match($pattern, $input, $match); 52 $name = $match['name'] ?? ''; 53 $comment = $match['comment'] ?? ''; 54 // 外側のカッコを切り取り 55 $comment = mb_substr($comment, 1, -1, 'UTF-8'); 56 $name = $name === '' ? null : $name; 57 $comment = $comment === '' ? null : $comment; 58 return compact('name', 'comment'); 59} 60 61$res = parse('二郎「男の中の「男」です」'); 62var_dump($res); 63 64/* ②箇所とも削除した結果 65 ["name"]=>null 66 ["comment"]=>null 67*/ 68 69/* 本来の(削除前の)結果 70 ["name"]=> string(6) "二郎" 71 ["comment"]=> string(27) "男の中の「男」です" 72*/ 73
③ <name>のグループ化の方の該当部分だけを削除して実行する(正常動作する)
PHP
1/* <name>の方の該当部分だけ削除して得られた結果 2 ["name"]=> string(6) "二郎" 3 ["comment"]=> string(27) "男の中の「男」です" 4*/
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2021/12/22 08:20 編集
2021/12/22 09:17
2021/12/22 10:57 編集