327
246

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

LIFULLAdvent Calendar 2022

Day 7

たった4文字でコード検索の精度がブチあがる正規表現

Last updated at Posted at 2022-12-06

この記事は、不動産情報サイト LIFULL HOME'S などを運営する株式会社LIFULLLIFULL Advent Calendar 2022 の記事です。

まだまだ入社1年目、株式会社LIFULLの暴れ回る新卒、 @pal4de です。
正規表現が大好きです。

これは、その中でもとくにお気に入りな正規表現「単語境界 \b」の検索における威力を説き、褒め称える記事です。
「正規表現、まァ基本は一通り勉強したな...」 というあなたにオススメしたい、ステップアップにピッタリなヤツです。

これは何?

改めて、 正規表現パターン \b は「単語境界」を表す記法です1
Word BoundaryのBですね。
ここでは、「単語」は単語構成文字 \w = [A-Za-z0-9_] の連続と定義します2

挙動の例

実際の挙動を見てみるとこんな感じ3

正規表現 検索対象文字列 マッチする位置
\b let count; |let| |count|;
\b snake_case |snake_case|
\b kebab-case |kebab|-|case|
\b 1: IMAGE001 |1|: |IMAGE001|
\bimage\b var image, imageSize, yourImage; var image, imageSize, yourImage;

アンダースコア_の扱いがやや意外ですが4、おおよそ直感的ではないでしょうか。ご覧の通り「単語の両端にマッチする」雰囲気が感じ取れます。

文頭^や文末$などと同様、\bは文字そのものではなく文字の隣にマッチする表現です5

特に嬉しさを表現しているのが一番最後のimageの例。
パターン \bimage\bimageの両サイドに単語境界\bが引かれている表現となっています。
つまり、日本語に意訳するなら「ちょうどピッタリimageにマッチする」ぐらいの意味になります。

何がうれしい?

先ほど挙げた例で、grepやVSCodeのファイル横断検索を使用したことがあるなら嬉しさがわかってくるのではないでしょうか。

そう、Language Serverなどによるリッチな言語サポートがなくとも、\bの 2文字×2=4文字 で変数名や関数名などのトークンの厳密な一致による検索が行えるようになるわけです。
この単語境界\bは、新しい6GitHub Code Searchでも使用可能というのですから喜びはひとしおです。

もう少し具体的な例として /\buser\b/i をした例を示します。

下記のようにプレフィックスやサフィックスに惑わされない検索が行えるようになり、検索結果ノイズもグッと減ります。

マッチする マッチしない
$|user| = $user_type =
class |User|() class UserOrganization()
"./|user|.php" "./special_user.php"

そして次回予告へ

さらに、「変数はいらないなあ...」とか「CSSのクラス名だから-の場合は区切りとみなしたくないなあ...」みたいな場合には検索クエリに肯定先読み否定先読み肯定後読み否定後読みを組み合わせて検索結果をさらに絞り込んでいくことになります。

みんなが苦手なヤツです。羅列の仕方もイヤな感じを演出しています。

(肯定|否定)[先後]読み編」もぜひご覧ください👇

まとめ

  • \bは文字ではなく、単語境界を表します。
  • 単語とは[A-Za-z0-9_]+で表されるものです。
  • 正規表現を使った検索時、\bで両端を挟んでやることにより、プレフィックス等が紛れ込まなくなり、regex searchが捗ります。

弊社アドベントカレンダーの他の記事もお楽しみください👇


オマケ

等価な表現

\b(?<=\W|^)(?=\w)|(?<=\w)(?=\W|$)と等価です。恐らく。

日本語に書き下すなら次のような感じです。

断片 日本語訳
(?<=\W|^) マッチ開始位置より左隣が「非単語構成文字または文字列先頭」
(?=\w) この位置より右隣が単語構成文字
| または
(?<=\w) この位置より左隣が単語構成文字
(?=\W|$) この位置より右隣が「非単語構成文字または文字列終端」

逆の表現 \B

ちなみに、\Bで逆の意味、つまり「単語の境界以外」になります。

使ったことはありません。

大文字で逆の意味になるのは正規表現あるあるですね。大変大変覚えやすい。


ここまで読んでくれてありがとう 😘

  1. 言語や処理系によって実装依存が激しい正規表現ですが、ほとんどのケースで使えます!!!

  2. 正規表現の処理系によってはロケールに依存しますが、あまり心配しなくても多分大丈夫

  3. 大文字・小文字を区別しないものとして見て下さい

  4. 多くの言語ではこれらの文字が連続が変数や関数名として扱われることからこのようになっていると考えられます。「単語」という名前が誤解を与えている

  5. このような表現をアンカーと呼びます。ちなみに.とか[a-z]は文字クラスと言います。

327
246
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
327
246

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?