grepの結果を反転させる方法

2 min read読了の目安(約2000字

概要

grep コマンドについて

  • 出力される行を反転させる方法
  • 終了ステータスを反転させる方法

を説明する。なお、エラーになる場合については考慮しない。

出力される行を反転させる

マッチする行を出力するのではなく、マッチしない行を出力させるには、-v オプションをつける。

$ printf "abc\nbcd\ncde\n"
abc
bcd
cde
$ printf "abc\nbcd\ncde\n" | grep b
abc
bcd
$ printf "abc\nbcd\ncde\n" | grep -v b
cde

終了ステータスを反転させる

マッチする行がある場合に0以外の終了コード、マッチする行がない場合に終了コード0にする。

入力が1行と仮定できる場合

入力が1行ならば、その1行が条件にマッチするか、しないかで終了コードが決まる。

$ echo -n "abc" | grep -q c ; echo $?
0
$ echo -n "abc" | grep -q d ; echo $?
1

したがって、-v オプションをつけることで終了ステータスを反転できる。

$ echo -n "abc" | grep -q -v c ; echo $?
1
$ echo -n "abc" | grep -q -v d ; echo $?
0

任意行の入力の場合

入力が1行と仮定できない場合、すなわち

  • 入力が0行になり得ること
  • 入力が2行以上になり得ること

の考慮も必要な場合には、-v オプションでは終了ステータスが反転するとは限らない。以下は反例である。

$ echo -n | grep -q a ; echo $?
1
$ echo -n | grep -q -v a ; echo $?
1
$ printf "abc\nbcd\ncde" | grep -q b ; echo $?
0
$ printf "abc\nbcd\ncde" | grep -q -v b ; echo $?
0

終了ステータスを反転するには、パイプラインの先頭に ! を付ければ良い。

$ echo -n | grep -q a ; echo $?
1
$ ! echo -n | grep -q a ; echo $?
0
$ printf "abc\nbcd\ncde" | grep -q b ; echo $?
0
$ ! printf "abc\nbcd\ncde" | grep -q b ; echo $?
1

まとめ

grepコマンドに関する二種類の反転について説明した。

  • grepの-vオプションで出力を反転する
  • シェルの!でコマンドの終了ステータスを反転する

後者はコマンドの出力に特定の文字列が含まれた場合にCIを失敗させるなどに活用できる。

確認環境

文中のコマンドの実行は以下の環境を用いた

$ bash --version
GNU bash, version 5.0.16(1)-release (x86_64-pc-linux-gnu)
Copyright (C) 2019 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
$ grep --version
grep (GNU grep) 3.4
Copyright (C) 2020 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Written by Mike Haertel and others; see
<https://git.sv.gnu.org/cgit/grep.git/tree/AUTHORS>.