マッチしなかった要素を探す

ちょっと表現が微妙なんだけど

  • 正規表現マッチを使い
  • マッチしない要素(行など)

を探す方法が急に気になったのでまとめてみた。

grep -v

GNU grep, BSD grep の場合は -v オプションが使える。–invert-match で、まさに「マッチしなかった行を探す」目的に使う。

awk '!/RE/'

awk の場合は基本的な動作を

パターン { アクション }

で記述する。このパターンを ! で否定すればマッチしない場合の動作を簡単に記述できる。

フィールドなどを明示する場合は

$1 ~ /RE/

がマッチするパターンで

$1 !~ /RE/

がマッチしないパターンになる。この ~, !~ の書き方は他の多くの LL にも採用されている。少なくとも Perl, Ruby では ~ を =~ で置き換えるだけでパターンの部分は記述できる。

Perl の grep()

Perl には list の中から特定のパターンにマッチする要素だけを抜き出す grep() 関数がある。これは

grep( /RE/, LIST )

という形で使う1。このとき !/RE/ とすればマッチしないものだけを抜き出せる。

Ruby の Enumerable#grep()

Ruby には Perl の grep によく似た機能があって、それが Enumerable#grep(). 構文こそ違うけど、働きはよく似ている。ただし、

Enumerable#grep( !/RE/ )

とは書けない。どうするのかなぁと思ったけど、こう書くしかないのかな?

Enumerable#select { |e| e !~ /RE/ }
Enumerable#find_all { |e| e !~ /RE/ }
Enumerable#reject { |e| e =~ /RE/ }

最近は find_all が有名っぽいので find_all で否定のマッチを書く場合が多いのかも。reject は意味は分かるけどまどろっこしい感じがする。

PHP の preg_grep()

PHP には PCRE を使って正規表現周りの機能を実現している preg_XXX() 関数群があって、この中に Perl の grep() のような preg_grep() がある。ただし、PHP には正規表現リテラルはないので

preg_grep( !/RE/, array() )

のようには書けない。どうするかというと、

preg_grep( '/RE/', array(), PREG_GREP_INVERT )

のように第3引数に PREG_GREP_INVERT という定数を与えてやる。

sed -ne '/RE/!p'

[2010-10-123 追記]

Twitter / eban: @finalfusion えー? sed -ne ' …

さらにツッコミがあったので。場外場外。

sed 使ってないので未確認で垂れ流しますよ。

[2010-10-11 追記]

Twitter でツッコミがあったので。

sed の説明はしません(笑)

改めて思うと !/RE/ の書き方は awk じゃなくて sed 由来かな? あるいはもしかして ed ? じゃないよな、たぶん。

  1. だけじゃないけど 

More