grep まとめ

# grep まとめ
grep技をまとめてみました。
思い出したら追記していきます。

利用するログ(適当に手元のnginxのログを加工してみただけ....)

```:zsh
$ cat access.log
127.0.0.1 - - [12/Dec/2015:13:23:32 +0900] "GET / HTTP/1.1" 200 612 "-" "curl/7.43.0"
127.0.0.1 - - [12/Dec/2015:13:23:37 +0900] "GET /hoge HTTP/1.1" 404 168 "-" "curl/7.43.0"
127.0.0.1 - - [12/Dec/2015:13:24:25 +0900] "GET /?fuga=0 HTTP/1.1" 200 612 "-" "curl/7.43.0"
127.0.0.1 - - [12/Dec/2015:13:24:38 +0900] "GET /hoge?fuga=0 HTTP/1.1" 404 168 "-" "curl/7.43.0"
127.0.0.1 - - [12/Dec/2015:13:25:44 +0900] "GET /50x.html HTTP/1.1" 500 537 "-" "curl/7.43.0"
127.0.0.1 - - [12/Dec/2015:13:35:56 +0900] "GET /gethost HTTP/1.1" 200 612 "-" "curl/7.43.0"127.0.0.1 - - [12/Dec/2015:13:39:02 +0900] "GET / HTTP/1.1" 200 612 "-" "curl/7.43.0"
$ cat error.log
2015/12/12 13:23:37 [error] 33901#0: *2 open() "/usr/local/Cellar/nginx/1.8.0/html/hoge" failed (2: No such file or directory), client: 127.0.0.1, server: localhost, request: "GET /hoge HTTP/1.1", host: "localhost:8080"
2015/12/12 13:24:38 [error] 33901#0: *4 open() "/usr/local/Cellar/nginx/1.8.0/html/hoge" failed (2: No such file or directory), client: 127.0.0.1, server: localhost, request: "GET /hoge?fuga=0 HTTP/1.1", host: "localhost:8080"
2015/12/12 13:53:51 [emerg] 38309#0: unexpected "{" in /usr/local/etc/nginx/nginx.conf:18
```

## 特定の文字列を含む行を取り出す

- 文字列で検索  
`grep [文字列] ファイル`  
hogeを含む行を取り出し

```:zsh
$ grep hoge access.log
127.0.0.1 - - [12/Dec/2015:13:23:37 +0900] "GET /hoge HTTP/1.1" 404 168 "-" "curl/7.43.0"
127.0.0.1 - - [12/Dec/2015:13:24:38 +0900] "GET /hoge?fuga=0 HTTP/1.1" 404 168 "-" "curl/7.43.0"
```

- 正規表現で検索  
`egrep [正規表現] ファイル` or `grep -E`  
１３時２３〜２５分まで抽出

```:zsh
$ egrep '13:2[3-5]' access.log
127.0.0.1 - - [12/Dec/2015:13:23:32 +0900] "GET / HTTP/1.1" 200 612 "-" "curl/7.43.0"
127.0.0.1 - - [12/Dec/2015:13:23:37 +0900] "GET /hoge HTTP/1.1" 404 168 "-" "curl/7.43.0"
127.0.0.1 - - [12/Dec/2015:13:24:25 +0900] "GET /?fuga=0 HTTP/1.1" 200 612 "-" "curl/7.43.0"
127.0.0.1 - - [12/Dec/2015:13:24:38 +0900] "GET /hoge?fuga=0 HTTP/1.1" 404 168 "-" "curl/7.43.0"
127.0.0.1 - - [12/Dec/2015:13:25:44 +0900] "GET /50x.html HTTP/1.1" 500 537 "-" "curl/7.43.0"
```

- 大文字小文字を区別しないで検索  
`grep -i [文字列] ファイル`

```:zsh
$ grep get access.log
127.0.0.1 - - [12/Dec/2015:13:35:56 +0900] "GET /gethost HTTP/1.1" 200 612 "-" "curl/7.43.0"

$ grep -i get access.log
127.0.0.1 - - [12/Dec/2015:13:23:32 +0900] "GET / HTTP/1.1" 200 612 "-" "curl/7.43.0"
127.0.0.1 - - [12/Dec/2015:13:23:37 +0900] "GET /hoge HTTP/1.1" 404 168 "-" "curl/7.43.0"
127.0.0.1 - - [12/Dec/2015:13:24:25 +0900] "GET /?fuga=0 HTTP/1.1" 200 612 "-" "curl/7.43.0"
127.0.0.1 - - [12/Dec/2015:13:24:38 +0900] "GET /hoge?fuga=0 HTTP/1.1" 404 168 "-" "curl/7.43.0"
127.0.0.1 - - [12/Dec/2015:13:25:44 +0900] "GET /50x.html HTTP/1.1" 500 537 "-" "curl/7.43.0"
127.0.0.1 - - [12/Dec/2015:13:35:56 +0900] "GET /gethost HTTP/1.1" 200 612 "-" "curl/7.43.0"
127.0.0.1 - - [12/Dec/2015:13:39:02 +0900] "GET / HTTP/1.1" 200 612 "-" "curl/7.43.0"

```

## 特定の文字列を含まない
`grep -v 文字列 ファイル`
今までのオプションなども併用可能 
` 200 `を含まない行を抽出

```:zsh
$ grep -v ' 200 ' access.log
127.0.0.1 - - [12/Dec/2015:13:23:37 +0900] "GET /hoge HTTP/1.1" 404 168 "-" "curl/7.43.0"
127.0.0.1 - - [12/Dec/2015:13:24:38 +0900] "GET /hoge?fuga=0 HTTP/1.1" 404 168 "-" "curl/7.43.0"
127.0.0.1 - - [12/Dec/2015:13:25:44 +0900] "GET /50x.html HTTP/1.1" 500 537 "-" "curl/7.43.0"
```

## 文字列を固定して検索(正規表現を無効)
grepでもちょっとした正規表現利用できてしまう弊害 
`'[error]'`が正規表現になってしまっているので、`e`or`r`or`o`が含まれたらマッチになっている

```:zsh
$ grep '[error]' error.log
2015/12/12 13:23:37 [error] 33901#0: *2 open() "/usr/local/Cellar/nginx/1.8.0/html/hoge" failed (2: No such file or directory), client: 127.0.0.1, server: localhost, request: "GET /hoge HTTP/1.1", host: "localhost:8080"
2015/12/12 13:24:38 [error] 33901#0: *4 open() "/usr/local/Cellar/nginx/1.8.0/html/hoge" failed (2: No such file or directory), client: 127.0.0.1, server: localhost, request: "GET /hoge?fuga=0 HTTP/1.1", host: "localhost:8080"
2015/12/12 13:53:51 [emerg] 38309#0: unexpected "{" in /usr/local/etc/nginx/nginx.conf:18
```

`'[error]'`を指定して抽出したい場合
`fgrep [文字列] ファイル` or `grep -F`

```:zsh
$ grep -F '[error]' error.log
2015/12/12 13:23:37 [error] 33901#0: *2 open() "/usr/local/Cellar/nginx/1.8.0/html/hoge" failed (2: No such file or directory), client: 127.0.0.1, server: localhost, request: "GET /hoge HTTP/1.1", host: "localhost:8080"
2015/12/12 13:24:38 [error] 33901#0: *4 open() "/usr/local/Cellar/nginx/1.8.0/html/hoge" failed (2: No such file or directory), client: 127.0.0.1, server: localhost, request: "GET /hoge?fuga=0 HTTP/1.1", host: "localhost:8080"
# または[]をエスケープ
$ grep '\[error\]' error.log
2015/12/12 13:23:37 [error] 33901#0: *2 open() "/usr/local/Cellar/nginx/1.8.0/html/hoge" failed (2: No such file or directory), client: 127.0.0.1, server: localhost, request: "GET /hoge HTTP/1.1", host: "localhost:8080"
2015/12/12 13:24:38 [error] 33901#0: *4 open() "/usr/local/Cellar/nginx/1.8.0/html/hoge" failed (2: No such file or directory), client: 127.0.0.1, server: localhost, request: "GET /hoge?fuga=0 HTTP/1.1", host: "localhost:8080"
```

## 検索を重ねる
grepを`|`(パイプ)で重ねる
` 200 `を含み、１３時２０分台のログを抽出

```:zsh
$ grep ' 200 ' access.log | grep '2015:13:2'
127.0.0.1 - - [12/Dec/2015:13:23:32 +0900] "GET / HTTP/1.1" 200 612 "-" "curl/7.43.0"
127.0.0.1 - - [12/Dec/2015:13:24:25 +0900] "GET /?fuga=0 HTTP/1.1" 200 612 "-" "curl/7.43.0"
```

## 複数の条件で検索
`grep -e [文字列] -e [文字列] ... ファイル`
` 200 `を含むまたは` 500 `を含む行を抽出 
egrepを利用して正規表現でも可能

```:zsh
$ grep -e ' 200 ' -e ' 500 ' access.log
127.0.0.1 - - [12/Dec/2015:13:23:32 +0900] "GET / HTTP/1.1" 200 612 "-" "curl/7.43.0"
127.0.0.1 - - [12/Dec/2015:13:24:25 +0900] "GET /?fuga=0 HTTP/1.1" 200 612 "-" "curl/7.43.0"
127.0.0.1 - - [12/Dec/2015:13:25:44 +0900] "GET /50x.html HTTP/1.1" 500 537 "-" "curl/7.43.0"
127.0.0.1 - - [12/Dec/2015:13:35:56 +0900] "GET /gethost HTTP/1.1" 200 612 "-" "curl/7.43.0"
127.0.0.1 - - [12/Dec/2015:13:39:02 +0900] "GET / HTTP/1.1" 200 612 "-" "curl/7.43.0"
```

## 行番号を付与
`grep -n [他オプション] ... ファイル`
先頭に行番号が付与される

```:zsh
$ grep -n -e ' 200 ' -e ' 500 ' access.log
1:127.0.0.1 - - [12/Dec/2015:13:23:32 +0900] "GET / HTTP/1.1" 200 612 "-" "curl/7.43.0"
3:127.0.0.1 - - [12/Dec/2015:13:24:25 +0900] "GET /?fuga=0 HTTP/1.1" 200 612 "-" "curl/7.43.0"
5:127.0.0.1 - - [12/Dec/2015:13:25:44 +0900] "GET /50x.html HTTP/1.1" 500 537 "-" "curl/7.43.0"
6:127.0.0.1 - - [12/Dec/2015:13:35:56 +0900] "GET /gethost HTTP/1.1" 200 612 "-" "curl/7.43.0"
7:127.0.0.1 - - [12/Dec/2015:13:39:02 +0900] "GET / HTTP/1.1" 200 612 "-" "curl/7.43.0"
```

## 検索にマッチした部分のみ抽出
`grep -o [文字列] ファイル`

```:zsh
$ grep -o '12/Dec/2015:13:2'  access.log
12/Dec/2015:13:2
12/Dec/2015:13:2
12/Dec/2015:13:2
12/Dec/2015:13:2
12/Dec/2015:13:2

$ egrep -o '12/Dec/2015:13:2[0-9]'  access.log
12/Dec/2015:13:23
12/Dec/2015:13:23
12/Dec/2015:13:24
12/Dec/2015:13:24
12/Dec/2015:13:25
```

## 検索にマッチする行が存在するファイル名を表示
`grep -l [文字列] ファイル`
`hoge`が内部に含まれるファイル名のみ表示

```:zsh
$ grep -l hoge *
access.log
error.log
```

## 検索にマッチする行が存在しないファイル名を表示
`grep -l [文字列] ファイル`
`error`が内部に含まれないファイル名を表示

```:zsh
$ grep -L error *
access.log
```

## 抽出しないで、色だけつける
grepにcolorが設定されていれば抽出されてマッチした文字列に色がつきますが、
抽出しないで文字列に色だけ付けたい場合ありますよね。
その場合は`-E`または`egrep`の席表現を利用して末尾が含まれるようにすると、
すべての文字列が出力されますが、マッチした文字列には色がつきます。

![スクリーンショット 2015-12-12 19.08.09.png](https://qiita-image-store.s3.amazonaws.com/0/31262/0bc3fef8-179e-7df5-986b-e9730bef70fe.png)

## 色んな色をつける
抽出しないで色がつけれるなら、文字列毎に色変えたかったりしますよね(warn|error|crit|etc...) 
grepの色は`GREP_COLOR`という変数で決定されるのでgrepをパイプで渡す度に変更してやります。

![スクリーンショット 2015-12-12 19.22.16.png](https://qiita-image-store.s3.amazonaws.com/0/31262/69009d71-956b-86ac-c4f4-6c0a956e6069.png)


また`--color=always`は色を次に引き継がせるオプションで、defaultだと`--color=auto`になってると思います。
つけていないと以下のように、最後のgrepの結果だけ色がつく残念な状態になります。
![スクリーンショット 2015-12-12 19.19.39.png](https://qiita-image-store.s3.amazonaws.com/0/31262/c175a69e-e0b0-7bc7-34f7-f2ea499c4cd3.png)