My External Storage

May 4, 2019 - 2 minute read - Comments - grep CLI

正規表現の文字クラス(角括弧[])にハイフンを含みたいときは、ハイフンを最初または最後に書く

正規表現をいじっていたらハマったのでメモ。

TL;DR

  • 文字クラス([])でハイフン(-)を指定しているつもりがちゃんと判定されない
  • 文字クラスの中でハイフンを指定するときは最初か最後にハイフンを置かないと範囲指定あつかいされてしまう。

文字クラス([])でハイフン(-)を指定しているつもりがちゃんと判定されない

Makefileの自己文書化をしていた。

上述のリンク先では以下のようなワンライナーが紹介されている。 このワンライナーでは、序盤の@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST)部分でMakefile内の対象行を拾って後続の処理を行なっている。

.PHONY: help

help:
    @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'

私のMakefileにはmake docker.runなどのようなドット(.)を含むコマンド定義があったが、この正規表現にドットは含まれていない。
そのため、上記の正規表現中の^[a-zA-Z_-]の部分を^[a-zA-Z_-\.]と変更したところ、ハイフンを含む行がヒットしなくなってしまった。

文字クラスの中でハイフンを指定するときは最初か最後にハイフンを置かないと範囲指定扱いされてしまう。

\-とエスケープをして^[a-zA-Z_\-\.]のように書いても当然意味がなかった。結局検索して解決することができた。一次ソース(仕様)は見つけられなかった。(正規表現の仕様はWeb上には公開されていないのだろうか?)

節タイトルの通り、文字クラスの中でハイフン(-)を指定するときは最初か最後に指定しないといけないようだ。
^[a-zA-Z_-\.^[a-zA-Z_.\-]と書きかえることで、ハイフンを含んだ文も、ドットを含んだ文もgrepすることができる正規表現を書くことができた。

終わりに

正規表現は記号が検索しにくいというところもあってなかなか調べるのが難しい([]で囲う表記を文字クラスと呼ぶことも今回初めて知った)。 オライリー本を買ってちゃんと読むべきか。

参考

関連記事