✌️

grep(1) のオプション -v が -v である理由

2022/12/11に公開

grep(1) ってなに

Unix な世界には grep(1) というコマンドがあります。 これはファイルの中からあるパターンを含む (パターンに一致する) 行のみを抽出して表示するコマンドです。 試しにファイル /etc/passwd から root を含む行を表示してみましょう。

grep(1) を試してみる
% grep 'root' /etc/passwd
root:*:0:0:Charlie &:/root:/bin/csh
toor:*:0:0:Bourne-again Superuser:/root:
daemon:*:1:1:Owner of many system processes:/root:/usr/sbin/nologin

うん、確かに root を含む行を表示できているようです。

検索に利用するパターンには正規表現 regular expression を利用することもできます[1]。 これも試してみましょう。

正規表現を使って grep(1) してみる
% grep '^gr.p.$' /usr/share/dict/words
grape
graph
grapy
gripe
gripy
grope

一致「しない」行を抽出

grep(1) のデフォルト動作ではパターンに一致する行を表示しますが、パターンに一致しない行を表示することもできます。 そのような挙動をしてもらうためにはオプション -v を指定してあげます。 例えば、数字を含まない行を表示するには正規表現 [0-9] をパターンに指定し、オプション -v を添えます[2]

パターンに一致しない行を表示
% grep -v '[0-9]' /etc/os-release
NAME=FreeBSD
ID=freebsd
HOME_URL="https://FreeBSD.org/"
BUG_REPORT_URL="https://bugs.FreeBSD.org/"

どうして -v なのか — どうして grep なのか

しかしどうしてパターンに一致しない行を表示するオプションが -v なのでしょうか。 もっとわかりやすく reverse から -r だとか unmatch から -u だとかである方がそれっぽい感じがあります[3]

オプション -v の謎を解き明かすためには grep(1) それ自体の名前の由来を知る必要があります。 grep という名前は Unix の古き良きエディタ ed(1) のコマンド g/RE/p に由来します。 このコマンドは「正規表現 RE に一致する行全て (g) を表示 (p)」します。 これは grep(1) の仕事と同じです。 そして、grep(1) にオプション -v を渡したときと同じ仕事をする ed(1) のコマンドは v/RE/p です。

grep(1) は ed(1) の機能の一部が独立してできたコマンドであり、オプション -v もまた ed(1) の機能に由来しているのでした。

おわりに

おわりです。


参考

  • Brain W. Kernighan; Rob Pike. “第 1 章 初心者のための UNIX”. UNIX プログラミング環境. 石田晴久監訳; 野中浩一訳. ASCII DWANGO, 2017, p. 7–55, ISBN978-4-04-893057-4.
脚注
  1. 検索パターンには「正規表現利用する」が正しい表現です。 正規表現 root が文字列 root にしかマッチしないだけなのですから。 ↩︎

  2. EBCDIC を喋る環境にいるなどの理由で何も表示されない人は [0-9] の代わりに [[:number:]] を使うと望む結果を得られるかもしれません。 ↩︎

  3. 「馬鹿を言え! オプション -r は recursive の短縮形じゃい!」と思った人は grep(1) の初出である V6 UNIX のマニュアルを見てきてください。 そんなオプションはありませんから。 ↩︎

Discussion