質問: ![**/usr/local/bin/gcc**という文字列を**\b\/\w*\/\b**という正規表現(PHP)で走査したときの動作です。](https://teratail.storage.googleapis.com/uploads/contributed_images/02a6f77a25ea02440748690a4ef0616c.png) コチラで**/usr/local/bin/gcc**という文字列を**\b\/\w*\/\b**という正規表現(PHP)で走査したときの動作です。 正規表現のエスケープされた**\/**は、4.をみるとsの手前の位置を走査しているようにみえます。なぜ、sそのものを調べるのではなく単語境界の\bや先読みのようにsの手前にあたる位置を調べようとするのでしょうか。 エスケープされて文字としてのスラッシュになったのだから、正規表現aが文字列aを走査するとaの手前の位置を調べるのではなくaそのものを調べるように**\/**は、手前の位置ではなく文字そのものを調べないのでしょうか。 --- また5行目でバックトラック(赤い矢印の部分)が発生していますが、*や+のような量指定子以外でもバックトラックは発生するのでしょうか。
回答: > > 正規表現のエスケープされた\/は、4.をみるとsの手前の位置を走査しているようにみえます。なぜ、sそのものを調べるのではなく単語境界の\bや先読みのようにsの手前にあたる位置を調べようとするのでしょうか。 > > > 正規表現は最初の1文字目から1文字ずつ、マッチする文字列集合を見つけようとするため、最初の単語`usr`の単語境界`↓usr`の「↓」位置にマッチしますが、その次の正規表現は`\/`なので、`usr`にはマッチしません。 ※「↓」記号は単語境界(記号は含まない)の意味 試しに、最初の正規表現パターンの`\b`が`usr`の最初にマッチしていることを確認するために、下記のように入力してみてください。下記どれでも同じ結果になります。 1. \busr\/ 2. \/\busr\/ 3. \/\busr\b\/ 下記の正規表現の意味は「**↓/ゼロ個以上の文字列**」となります。 ``` \b\/\w* ``` 全文を図式で表すと下記のようになります。 ``` ^/↓usr↓/↓local↓/↓bin↓/↓gcc↓$ ※上記「↓」記号は単語境界(記号は含まない)の意味 ``` 正規表現の`\b`は単語境界(記号は含まない)なので、自然な正規表現を書くのであれば下記のようにします。下記のように書くと、`/usr/, /bin/`にマッチします。`//g`フラグなしの場合は`/usr/`のみにマッチします。 ``` \/\b\w+\b\/ ``` > > また5行目でバックトラック(赤い矢印の部分)が発生していますが、*や+のような量指定子以外でもバックトラックは発生するのでしょうか。 > > > この場合のバックトラックは、あくまでも指定の正規表現が最初の`/usr`でマッチしなかったので、マッチするまで最初からマッチさせようとしていることを示すものです。そして、`\b\/\w*`で`↓/local`にマッチしたというわけです。 ちなみにこの正規表現の動作は`PHP`、`Perl`、`JavaScript`、`sed`などでも同じように振舞います。