正規表現入門

簡易的なまとめはこちら

1. コマンド紹介(grep)

このページでは,正規表現を実際にLinuxで使えるように,例を出しながら解説していきます.そこで,例の中で使うコマンドを先に紹介します.

grepは,テキストの中からパターンに一致する文字列を含む行を出力するコマンドです.例えば,次のような出力をするプログラムがあるとします.

# $マークから始まる行は入力,プログラム名はprogとする.
$ prog
1,Taro,Antarctic
2,Jiro,Antarctic
3,John,Yamanashi
4,shirou,Hyougo

このとき,南極(Antarctic)という文字列が含まれる行だけを抜き取りたいとします.そういう場合は次のようにパイプを使って実現することができます.

$ prog | grep 'Antarctic'
1,Taro,Antarctic
2,Jiro,Antarctic

また,grepはオプションをつけることによって所謂,正規表現を扱うことができます.次のような,htmlファイルがあるとします.

<html>
    <body>
        <a href="https://www.google.com">Google</a>
        <a href="http://www.yahoo.co.jp">Yahoo</a>
    </body>
</html>

このファイルから正規表現を使ってURLだけを抜き取るには例えば,次のようにします.

# htmlファイルの名前をindex.htmlとする.
$ cat index.html | grep 'href' 
        <a href="https://www.google.com">Google</a>
        <a href="http://www.yahoo.co.jp">Yahoo</a>
$ cat index.html | grep 'href' | grep -Eo '"[^"]*"' | grep -Eo '[^"]*'
https://www.google.com
http://www.google.com

または,この場合は次のようにもできます.

$ cat index.html | grep -Eo '(http|https)[^"]+'
https://www.google.com
http://www.google.com

grepのオプションのEは拡張された正規表現(extended regexp)という意味で,oは一致したところだけを抜き出す(only matching)という意味です. また,このようにgrepは数珠つなぎにして使うことができます. 具体的にどのような処理を行っているかは,第2章から説明していきます.


2. 繰り返し

ここでは,正規表現の+,*,{3}について説明していきます.

次のような出力を行うプログラムがあるとします.

$ prog2
SaaE
SabE
SaabE
SaabbE
SabcE
SaabbccE
SababE

ここで,Sから始まり,aが2回出力された後ろにbが1回以上出力されて,Eで終わる行を抜き出すには,次のようにします.

$ prog2 | grep -Eo 'Sa{2}b+c*E'
SaabE
SaabbE
SaabbccE

ここで使った正規表現を一つずつ意味で分けると次のようになります.

S   : Sが1回だけ
a{2}: aが2回だけ
b+  : bが1回以上
c*  : cが0回以上(cがなくてもいい)
E   : Eが1回だけ

3. 複数文字指定

第2章の例で使ったプログラムを再利用します.

$ prog2
SaaE
SabE
SaabE
SaabbE
SabcE
SaabbccE
SababE

ここから,SとEの間にa,b,cのうちどれでもいいので3つ文字がある行を抜き出すには,次のようにします.

$ prog2 | grep -Eo 'S[a-c]{3}E'
SaabE
SabcE

ここで使った正規表現を一つずつ意味で分けると次のようになります.

S     : Sが1個だけ
[a-c] : アルファベットでaからcの間にある文字(a,b,c)のうちの任意の一文字
{3}   : [a-c]が3個繰り返されている
E     : Eが1個だけ

[a-z]とすれば小文字全てを指定することができます. また,[afk]とすると,{a,f,k}のうちのどれか1文字を意味します. [a-zA-Z]とすれば大文字小文字全てのアルファベットのうちの1文字という意味になります.

次に,第1章のhtmlファイルの例を使いまわしてみます.

<html>
    <body>
        <a href="https://www.google.com">Google</a>
        <a href="http://www.yahoo.co.jp">Yahoo</a>
    </body>
</html>

この中から,URLを取るのに次のようにしました.

$ cat index.html | grep -Eo '(http|https)[^"]+'
https://www.google.com
http://www.google.com

ここで使った正規表現を一つずつ意味で分けると次のようになります.

(http|https) : httpかhttpsという文字列が1個
[^"]+        : "という文字以外が1個以上
※ [^a]とすることでa以外の全ての文字のうちの1個という意味になります.

4. 任意の1文字

またまた,第2章の例を再利用します.

$ prog2
SaaE
SabE
SaabE
SaabbE
SabcE
SaabbccE
SababE

このとき,a,b,cに限らず何でもいいのでSとEの間に文字が4個以上10個以下ある行を抜き出すにはこのようにします.

$ prog2 | grep -Eo 'S.{4,10}E'
SaabbE
SaabbccE
SababE

ここで使った正規表現を一つずつ説明すると次のようになります.

S       : Sが1個だけ
.       : 任意の文字が1個(どんな文字でもいい)
.{4,10} : 何か文字が4個以上10個以下(どんな組み合わせの文字列でもいい)
E       : Eが1個だけ

5. 特別な記号

行頭,行末を表す特別な文字があります.文字を表すのではなく位置を表します. 次のような出力をするプログラムを考えます.

$ prog3
この池はとても広い.
    夏にはたくさんの人が泳ぎに来る.
冬は氷で覆われるので車で上を走ることができる.
    親子連れにとても人気な場所だ.
調べてみるとツアー特集などの情報がたくさん出てくる.
    特に流れるプールは人気なようだ.

このとき,行頭が空白ではない行を抜き出すには以下のようにします.

$ prog3 | grep -Eo '^[^ ]*'
この池はとても広い.
冬は氷で覆われるので車で上を走ることができる.
調べてみるとツアー特集などの情報がたくさん出てくる.

行頭・行末は次の2つの文字で表します.

^ : 行頭を表す
$ : 行末を表す
Tweet