例えばこんなテキストがあって

# regex.txt
key1 aaa
aaa key2
key1 aaa key2
key3 aaa
aaa key4

それぞれこんな条件でgrepをするケースを想定

  • OR条件(key1で始まるかkey2で終わる)

    grep -E '^key1|key2$' regex.txt
    
  • 否定のOR条件(key1以外で始まるかkey2以外で終わる)

    grep -v -e '^key1' -e 'key2$' regex.txt
    # perl互換 正規表現
    grep -P '^(?!key1)|^.*(?<!key2)$' regex.txt
    
  • AND条件(key1で始まりkey2で終わる)

    grep '^key1.*key2$' regex.txt
    
  • 否定のAND条件(key1以外で始まりkey2以外で終わる)

    grep -v '^key1' regex.txt | grep -v 'key2$'
    # perl互換 正規表現
    grep -P '^(?!key1).*(?<!key2)$' regex.txt
    

否定系のOR/AND条件を実現しようとすると-eオプションを複数書いたり、
パイプで別のgrepをつなげたりする必要が出てくる。
上のようにPオプションでperl互換(PCRE)に対応させると先後読みが
使えるようになるのでgrep一発でやりたい場合はいいかも。

mac(Mountain Lion)にGNU grepを導入

ちなみに、macのgrepはデフォルトがBSD grepなので-Pオプションが使えない。。。
のでGNU grepを導入する

$ brew update
$ brew tap homebrew/dupes
$ brew versions grep
$ brew install homebrew/dupes/grep
# GNU grepはggrepコマンドになる
$ ggrep -V

上の例でPオプションを使っている例でgrepをggrepと読み替えて実行出来ればOK

rubyのワンライナーでgrep

自分は、正規表現の方言とかに悩まされるのが嫌なのでちょっと複雑な正規表現が
必要な時はrubyの使い捨てワンライナーで処理したりしてる
ruby(その他の言語もほぼそうだけど)の正規表現はほぼPCRE互換なので
正規表現の方言で悩む事もほぼ無いと思う。

上と同じOR/ANDのgrepをrubyのワンライナーでやるとこんな感じ

  • OR条件(key1で始まるかkey2で終わる)

    ruby -e 'puts $<.grep /^key1|key2$/' regex.txt
    
  • 否定のOR条件(key1以外で始まるかkey2以外で終わる)

    ruby -e 'puts $<.grep /^(?!key1)|^.*(?<!key2)$/' regex.txt
    
  • AND条件(key1で始まりkey2で終わる)

    ruby -e 'puts $<.grep /^key1.*key2$/' regex.txt
    
  • 否定のAND条件(key1以外で始まりkey2以外で終わる)

    ruby -e 'puts $<.grep /^(?!key1).*(?<!key2)$/' regex.txt