マッチしなかった要素を探す
ちょっと表現が微妙なんだけど
- 正規表現マッチを使い
- マッチしない要素(行など)
を探す方法が急に気になったのでまとめてみた。
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 追記]
sed の説明はしません(笑)
改めて思うと !/RE/ の書き方は awk じゃなくて sed 由来かな? あるいはもしかして ed ? じゃないよな、たぶん。
だけじゃないけど ↩