grepを用いた正規表現検索 例題と解説

##はじめに
ひよっこエンジニアです。初心者向けにgrepを用いた正規表現検索についてまとめています。また、様々なパターンを調べるために、簡単な問題と解説を用意したのでトライしてみてください。

##正規表現
記号や文字列を組み合わせて、目的のキーワードを見つけるためのパターンを作り、検出する方法。
記号は`メタキャラクタ`と呼ばれ、記号にそれぞれ意味がある。

##主なメタキャラクタ

|記号|意味|備考|
|:---:|:---:|:---:|
|^|先頭||
|$|末尾||
|\|直後の一文字をエスケープ||
|.|任意の一文字||
|*|直前の文字が0回以上繰り返し||
|?|直前の文字が0回か1回繰り返し|拡張正規表現|
|+|直前の文字が1回以上繰り返し|拡張正規表現|
|{ }|直前の文字を{}の回数繰り返し|拡張正規表現|
|[ ]|[ ]で囲まれた文字のうち一文字に一致|

`?`や`+`は拡張正規表現と呼ばれ、

- `egrep`コマンド
- `grep`に`-E`オプション をつけた場合

に使用することができる。

##[ ]による文字グループ
|例|意味|
|:---:|:---:|
|[abc]|a,b,cのいずれかの文字|
|[a-c]|a,b,cのいずれかの文字(上と同じ)|
|[a-cA-C]|a,b,c,A,B,Cのいずれかの文字|
|[^abc]|a,b,c以外の文字|


#例題

以降、grepコマンドを用いて文字列を検索する例題を記述していく。

```
※grepコマンドの使い方
$grep {検索したい文字列} {検索したいファイル名}

$ grep UNIX01 file1
UNIX01
```

##SECTION1



SECTION1は下記の例題とfile1でやっていきます。

```
【例題】
例1: $ grep '^U' file1
例2: $ grep '[xX]' file1
例3: $ grep '^U.*1$' file1
例4: $ grep '.' file1
例5: $ grep '\.' file1
例6: $ grep '^[^0-9]' fileA
```
```
$ cat file1
UNIX01
UNIX02
Linux01
Linux10
.
RedHat10
RedHat11
```

###例1
先頭がUで始まるの検索。

```
$ grep '^U' file1
UNIX01
UNIX02
```


###例2
x,Xが含まれている行の検索。

```
$ grep '[xX]' file1
UNIX01
UNIX02
Linux01
Linux10
```

###例3
先頭がUで始まり、任意の文字を0回以上繰り返して、最後は1で終わる行の検索。

```
$ grep '^U.*1$' file1
UNIX01
```


###例4
任意の一文字が含まれる行の検索。(＝ 空白行以外の全てを検索)

```
$ grep '.' file1
UNIX01
UNIX02
Linux01
Linux10
.
RedHat10
RedHat11
```

###例5
ピリオドを含む行の検索。
`\`の後の文字はエスケープされるため`.`はメタキャラクタではなく文字としてとらえる。


```
$ grep '\.' file1
.
```

###例6
先頭が数値以外の行を検索。

```
$grep '^[^0-9]' fileA
UNIX01
UNIX02
Linux01
Linux10
.
RedHat10
RedHat11
```

##SECTION2

SECTION2は下記の例題とfile2でやっていきます。

```
【例題】
例7: $ grep '[0-9][0-9]*' file2
例8: $ grep '[0-9]*' file2
例9: $ grep '1.bak' file2
例10: $ grep '1.' file2
例11: $ grep '^centOS[^0-9][^A-C].*k$' file2
例12: $ grep '^centOS0[^1-9]*.bak' file2
例13: $ grep -E '^centOS10?' file2
例14: $ grep -E '10|AA' file2
例15: $ grep -E '^centOS[^1-9]{5}.bak' file2
```

```
$ cat file2
centOS01.bak
centOS10.bak
centOS123.bak
centOS00000.bak
centOSAAA.bak
centOSABC.bak
centOS.bak
```

###例7
一桁の数値を含むor二桁以上の数値を含む行の検索。

```
$ grep '[0-9][0-9]*' file2
centOS01.bak
centOS10.bak
centOS123.bak
centOS00000.bak
```

###例8
0桁の数値を含むor一桁以上の数値を含む行の検索。

```
$ grep '[0-9]*' file2
centOS01.bak
centOS10.bak
centOS123.bak
centOS00000.bak
centOSAAA.bak
centOSABC.bak
centOS.bak
```

例⑦と比較すると分かるように、「0桁の数値を含む」≒ `全て`を含むことになり全行検索される。

###例9
`1.bak`が含まれる行の検索。

```
$ grep '1.bak' file2
centOS01.bak
```

###例10
1の後に任意の文字が含まれる行の検索。

```
$ grep '1.' file2
centOS01.bak
centOS10.bak
centOS123.bak
```

###例11
先頭が`centOS`から始まり、次に数値以外の文字、次にA,B,C以外の文字を0回以上繰り返して、kで終わる行の検索。

```
$ grep '^centOS[^0-9][^A-C].*k$' file2
centOS.bak
```


###例12
先頭が`centOS0`から始まり、次に1〜9以外の文字を0回以上繰り返して、.bakで終わる行の検索。

```
$ grep '^centOS0[^1-9]*.bak' file2
centOS00000.bak
```

###例13

先頭が`centOS1`から始まり、0が0回以上、もしくは1回の繰り返しに一致する検索。

```
$ grep -E '^centOS10?' file2
centOS10.bak
centOS123.bak
```
`?`は拡張正規表現で使用されるメタキャラクタで、`直前の文字が0回以上もしくは1回の繰り返しに一致`する。
`centOS123.bak`は？の直前の文字(=0)が0回の繰り返しの時に該当し、
`centOS10.bak`は？の直前の文字(=0)が1回の繰り返しの時に該当する。

-Eオプションは拡張正規表現を使用する際に付けなければならない。
また下記のようにegrepコマンドを使用することもできる。

```
$ egrep 'centOS10?' file2
centOS10.bak
centOS123.bak
```

###例14
`10`もしくは`AA`を含む行を検索。

```
$ grep -E '10|AA' file2
centOS10.bak
centOSAAA.bak
```
`|`を挟む左右のどちらかに一致する行を検索する。
これも拡張正規表現のため-Eオプションまたはegrepコマンドを使用する必要がある。

ちなみに、`|`を複数使用することも可能。

```
$ grep -E '10|AA|AB' file2
centOS10.bak
centOSAAA.bak
centOSABC.bak
```

###例15
先頭が`centOS`から始まって、`1~9`以外の文字を5回繰り返して、`.bak`で終わる行を検索。


```
$ grep -E '^centOS[^1-9]{5}.bak' file2
centOS00000.bak
```
`{}`が拡張正規表現のため-Eオプションまたはegrepコマンドを使用する必要がある。

##SECTION3

SECTION3は下記の例題と
序盤で作成したfile1をもう一度使ってやっていきます。

```
【例題】
例16: $ grep -i '[Ix]' file1
例17: $ grep -v '0.' file1
例18: $ grep -F '.' file1
```
```
$ cat file1
UNIX01
UNIX02
Linux01
Linux10
.
RedHat10
RedHat11
```

###例16

i,I,x,Xが含まれる行を検索。

```
$ grep -i '[Ix]' file1
UNIX01
UNIX02
Linux01
Linux10
```
-iオプションは小文字大文字の区別をしない。

###例17

0の後に任意の一文字が含まれる行以外を検索。

```
$ grep -v '0.' file1
Linux10
RedHat10
RedHat11
```
0の後に任意の一文字が含まれる行以外を検索する。
-vは指定されたパターン以外の行を検索するオプション。
下記のーvを付けなかった場合と比較すると理解しやすいかもしれない。

```
$ grep '0.' file1
UNIX01
UNIX02
Linux01
```

###例18

`.`を含む行を検索する。

```
$ grep -F '.' file1
.
```
-Fオプションは指定された文字列をそのまま検索するため、`.`をメタキャラクタとして扱わない。
-Fオプションを付けない場合、メタキャラクタとして扱われ
任意の一文字を含む行を検索するため下記のようになる。

```
$ grep '.' file1
UNIX01
UNIX02
Linux01
Linux10
.
RedHat10
RedHat11
```

ちなみに`$fgrep '.' file1`でも同じ挙動になる。


##終わりに
何か間違いがありましたらご指摘いただけると幸いです。