1    正規表現と grep コマンドによる情報の検索

この章では,正規表現とその使用方法について説明します。 一般に正規表現は,grep コマンドでパターンを照合するために使用されていますが,テキスト処理やフィルタ処理のためのその他のユーティリティやコマンドでも使用されます。grep コマンドについては,1.2 節で説明します。

この章は,次の事項について説明します。

1.1    正規表現

この節では,次の項目について説明します。

正規表現は,どのような文字列を照合するかを指定します。 正規表現は,テキスト文字列と演算子から構成されます。 テキスト文字列には照合する文字列を,演算子には反復,選択などの機能を指定します。

正規表現は次の 2 つのカテゴリに分けられます。

1.1.1 項および 1.1.2 項で,これらの各正規表現について説明します。 これらの項で説明する正規表現の他に,文字クラス,照合順序,等価クラスに関連する特殊な正規表現があります。 これらのクラスについての詳細は 1.1.6 項を参照してください。

これら 3 つの項で説明する正規表現演算子の優先順位は,次のとおりです。

  1. 照合関連のカッコ

    [= =][. .][: :]

  2. エスケープ文字

    \char

  3. カッコ式

    [expr]

  4. サブ正規表現

    基本正規表現の場合: \(expr\), \n

    拡張正規表現の場合: (expr)

  5. 繰り返し

    基本正規表現の場合: *, \{i\}, \{i,\}, \{i,j\}

    拡張正規表現の場合: *, ?, +, {i}, {i,}, {i,j}

  6. 連結

  7. 行頭,行末

    ^, $

  8. 二者択一 (拡張正規表現の場合)

    |

1.1.1    基本正規表現

基本正規表現は,より単純な基本正規表現を連結して構成されます。 アルファベット文字は普通のテキスト文字として扱われます。 テキスト文字は,常にその文字自身を照合します。 数字もテキスト文字として扱われます。 ただし,数字の前にバックスラッシュがある場合は反復式として処理されます。 反復式については,表 1-1 を参照してください。

たとえば,正規表現 rabbit は文字列 rabbit と一致し,正規表現 a57D は文字列 a57D と一致します。

文字と演算子で単純な基本正規表現が構成されます。 いくつかの単純な基本正規表現を組み合わせて,複雑な正規表現が構成されます。

表 1-1 に基本正規表現の規則を示します。

表 1-1:  基本正規表現の規則

正規表現 名称 説明
文字,数字,ほとんどの句読点 テキスト文字 その文字自身と一致します。
. ピリオド (ドット) 改行文字以外の任意の 1 文字と一致します。
* アスタリスク 直前の単純正規表現の 0 回以上の繰り返しと一致します。
\{i,j\} カウント式 直前の単一正規表現の繰り返し個数を指定します。 たとえば,ab\{3\}c は,abbbc のみと一致します。ab\{2,3\}c は,abbc または abbbc と一致し,abc または abbbbc とは一致しません。
\(expr\) サブ正規表現 (保存デリミタ) expr に指定した複数の基本正規表現演算子を 1 つの単位として扱います。 たとえば,a\(bc\)\{2,3\}dabcbcd あるいは abcbcbcd と一致します。abcd あるいは abcbcbcbcd とは一致しません。 この正規表現は,後で再使用できるように, 番号付き保存領域に格納されます。
\n 反復式 正規表現内の n 番目の保存デリミタの内容を繰り返します。
[chars] 大カッコ 大カッコ内の文字の任意の 1 文字と一致します。 ハイフンを使用すれば範囲指定ができます。 たとえば,[0-9a-z] は任意の一桁の数字または小文字と一致します。 大カッコ内では,ハイフンおよび山形記号を除いて,すべての文字をテキスト文字として処理します。
^ 山形記号 正規表現の最初に使用された場合,行頭を意味します。 大カッコ内で最初の文字に使用された場合,カッコ内の文字以外と一致します。 それ以外の場所では,特別な意味を持ちません。
$ ドル記号 正規表現の最後で使用された場合,行末を意味します。 それ以外の場所では,特別な意味を持ちません。
\char バックスラッシュ 大カッコ内にある場合を除いて,後続の 1 文字をエスケープすることにより,通常は正規表現演算子として使用される文字の照合を行いません。
expr expr ... 連結 連結した正規表現と一致する文字列を照合します。

1.1.2    拡張正規表現

基本的には,拡張正規表現は 1.1.1 項で説明した基本正規表現と同じです。 ただし拡張正規表現の場合,grep (-Eフラグを指定しない場合) や sed などのプログラムよりも強力なファイル操作およびフィルタ操作を行うためのプログラムである awk などの特定のプログラムで使用する,拡張された正規表現を含みます。 基本正規表現と拡張正規表現のそれぞれに含まれる正規表現の多くは同じものですが,これらの 2 つのタイプの正規表現は別のものとして考えるのがよいでしょう。表 1-2 に拡張正規表現の規則を示します。

表 1-2:  拡張正規表現の規則

正規表現 名称 説明
文字,数字,ほとんどの句読点 テキスト文字 その文字自身と一致します。
. ピリオド (ドット) 改行文字以外の任意の 1 文字と一致します。
* アスタリスク 直前の単純正規表現の 0 回以上の繰り返しと一致します。
? 疑問符 直前の単一正規表現と一致します。 0 回の場合も含みます。
+ プラス記号 直前の単一正規表現の 1 回以上の繰り返しと一致します。
{i,j} カウント式 直前の単一正規表現の繰り返し個数を指定します。 たとえば,ab{3}c は,abbbc のみと一致します。ab{2,3}c は,abbc または abbbc と一致し,abc または abbbbc とは一致しません。 基本正規表現のカウント式はエスケープされたカッコで範囲指定しますが,拡張正規表現の場合エスケープは不要です。 拡張正規表現を使用してカウント式形式のリテラル文字列を照合する場合は,左側のカッコをエスケープします。 たとえば,正規表現 \{2,3} は文字列 {2,3} を照合します。
(expr) サブ正規表現 expr に指定した複数の拡張正規表現演算子を 1 つの単位として扱います。 たとえば,a(bc)?dad あるいは abcd を照合します。abcbcd あるいは abcbcbcd などは照合しません。 基本正規表現の場合はエスケープされたカッコで範囲指定されますが,拡張正規表現の場合エスケープは不要です。 拡張正規表現を使用して,カッコで囲まれたリテラル文字列を照合する場合は,左側のカッコをエスケープします。 たとえば,正規表現 \(abc) は文字列 (abc) を照合します。
[chars] 大カッコ 大カッコ内の文字の任意の 1 文字と一致します。 ハイフンを使用すれば範囲指定ができます。 たとえば,[0-9a-z] は任意の一桁の数字または小文字と一致します。 大カッコ内では,ハイフンおよび山形記号を除いて,すべての文字をテキスト文字として処理します。
^ 山形記号 正規表現の最初に使用された場合,行頭を意味します。 大カッコ内で最初の文字に使用された場合,カッコ内の文字以外と一致します。 それ以外の場所では,特別な意味を持ちません。
$ ドル記号 正規表現の最後で使用された場合,行末を意味します。 それ以外の場所では,特別な意味を持ちません。
\char バックスラッシュ 大カッコ内にある場合を除いて,後続の 1 文字をエスケープすることにより,通常は正規表現演算子として使用される文字の照合を行いません。
expr expr ... 連結 連結した正規表現と一致する文字列を照合します。
expr|expr ... 縦線 連結した正規表現と一致する文字列を照合します。

1.1.3    正規表現の繰り返しとの照合

アスタリスク ( * ) は,直前の正規表現に作用し,照合パターンの 0 回以上の繰り返しを照合します。 ピリオドの後にアスタリスクを使用するとヌルを含む任意の文字列に照合します。 ピリオドとアスタリスクは,常に最長のテキストを照合しようとします。 次の例で考えてみましょう。

% echo "A B C D" | sed 's/^.* /E/'
ED

この例の sed ストリーム・エディタ・コマンドは,sed に,1 番目と 2 番目のスラッシュの間の正規表現を照合させ,照合したパターンを 2 番目と 3 番目のスラッシュの間の文字列に置換するものです。 この正規表現が照合するのは,行頭から始まり,任意の文字列を含み,スペースで終了する任意の文字列です。 文字列 "A " もこの式を満たしていますが,最長の照合パターンは "A B C " です。 したがって,sed は,"A B C " を "E" に置換し,ED を出力します。sed ストリーム・エディタについての詳細は,第 3 章を参照してください。

基本正規表現の場合も拡張正規表現の場合も,アスタリスクは直前の正規表現の任意回数の繰り返しを照合します。 プラス記号 ( + ) または疑問符 ( ? ) を使用すると,特定の拡張正規表現が照合する反復回数を限定することができます。 プラス記号を指定した場合,照合パターンの繰り返し回数は 1 回以上でなければなりません。 疑問符の場合,2 回以上の繰り返しは照合しません。

次の表は,アスタリスク,プラス記号,疑問符が照合する文字の例を示したものです。

正規表現 照合する文字列
ab?c ac abc  
ab*c ac abc abbc, abbbc, ...
ab+c   abc abbc, abbbc, ...

正規表現の繰り返し回数をさらに限定して指定することもできます。 次に示すのは,基本正規表現の繰り返し回数を指定するいくつかの方法です。

拡張正規表現の場合,バックスラッシュは不要です。 たとえば,上記の例の回数制限はそれぞれ ab{3}cab{3,}cab{2,4}c と指定します。

サブ正規表現デリミタ \ (および \) を使用すれば,サブ正規表現パターンとして 1 行で最高 9 つまでの基本正規表現を保管することができます。 行の左から右に数えて,1 番目に保管されたパターンは 1 番目の保管領域に,2 番目に保管されたパターンは 2 番目の保管領域に保管されます。

文字列 \n (n は 1〜9 までの 1 桁の数字) は,n 番目に保存されたパターンを照合します。 次のパターン例で考えてみましょう。

\(A\)\(B\)C\2\1
 

このパターンは文字列 ABCBA に照合します。 保管領域に保管するパターンはネストしてもかまいません。 カッコで囲まれているパターンがネストしているかどうかにかかわらず,n は,左から数えて n 番目に出現したデリミタを参照します。 また,正規表現 \n は,アドレス・パターンに使用することも,edsed などのエディタで置換文字列として使用することもできます。

1.1.4    選択した文字のみの照合

正規表現のピリオドは,改行文字以外の任意の文字を照合します。 照合する文字を限定するには,限定する文字を大カッコ ( [] ) で囲みます。 大カッコで囲まれた文字列は単一の正規表現であり,カッコで囲まれた任意の 1 文字を照合します。 山形記号 ( ^ ) を除いて,大カッコ内の正規表現演算子はテキスト文字として解釈されます。 大カッコの中の最初の文字として山形記号を使用すると,カッコ内に指定した文字以外を照合します。 その他の場所に指定した山形記号は,特別な意味を持ちません。

ダッシュを使用して文字の範囲を指定した場合 (たとえば [a-z]),指定範囲に含まれる文字は,LC_CTYPE 環境変数で設定されている現在の照合順序によって決定されます。 国際化機能および照合順序の使用方法についての詳細は,『Tru64 UNIX ユーザーズ・ガイド』 を参照してください。 ダッシュがカッコで囲まれた文字列の最初または最後の文字である場合,あるいは,山形記号がカッコ内の最初の文字で,ダッシュの直前にある場合には,ダッシュは特別な意味を持ちません。 カッコで囲む文字列の中に,右大カッコを含める場合は,右大カッコを最初に,あるいは先頭の山形記号の直後に指定してください。

grep ユーティリティで -i オプションを使用すると,大文字と小文字を区別しないで照合を行うことができます。-y オプションは,-i オプションと同一です。 その他のユーティリティで,大文字と小文字を区別しない正規表現を使用する場合や,部分的に大文字と小文字を区別しない正規表現を使用する場合には,カッコ内に指定する文字を大文字と小文字の両方で記述した正規表現を使用します。 次に例を示します。

% grep '[Jj]ones' group-list
 

1.1.5    複数の正規表現の指定

grep (-E フラグを指定した場合) や awk など,ユーティリティによっては縦線で正規表現を区分することによって,複数の正規表現を同時に指定することができます。 次に例を示します。

% awk '/[Bb]lack|[Ww]hite/ {print NR ":", $0}' .Xdefaults
55: sm.pointer_foreground:  black
56: sm.pointer_background:  white
 

1.1.6    正規表現における特別な照合

大カッコによるデリミタを使用して,クラスと呼ばれる特別なタイプの正規表現を指定することができます。

大カッコとコロンによるデリミタ [::] で文字クラス名を指定すると,指定した文字クラスに含まれる文字セットを照合します。 各文字セットのメンバは,LC_CTYPE 環境変数の現在の設定によって決定されます。 サポートされる文字クラスは,alnum, alpha, cntrl, digit, graph, lower, print, punct, space, upper, xdigit です。 たとえば,[[:lower:]] は現在のロケールのすべての小文字を照合します。

使用する照合順序によっては,複数の文字を 1 つの文字としてソートする場合があります。 たとえばハンガリー語の場合,文字列 csdz などはそれぞれ照合シンボルです (ハンガリー語の場合,第 1 ソート順序は aábccsddze,... です)。 このような特別な文字列を照合シンボルと呼び,大カッコとピリオドによるデリミタ [..] で囲むことによって指定することができます。 正規表現構文でこのデリミタを使用すると,複数文字の照合要素 (照合シンボル) と,その照合要素を構成する各文字とを区別することができます。

ハンガリー語の照合規則を使用する場合,[[.cs.]]cs を照合する 1 つの正規表現と見なされます。 一方,[cs]c または s を照合する正規表現と見なされます。 また,[a-[.cs.]] は,aábc,および cs を照合します。

照合要素を大カッコと等号によるデリミタ [==] で囲むことにより,文字に対して等価クラスを定義することができます。 等価クラスとして定義された文字は,すべて同じ第 1 ロケーションにソートされます。 等価クラスは,一般に 2 段階ソートを処理するために設計されています。 つまり,フランス語などのように,ある文字グループを同じ第 1 ロケーションにソートし,次にそれらの文字の第 2 次ソートを行うように定義するためのものです。 たとえば,eéê が同じ等価クラスに属している場合,[[=e=]fg][[=é=]fg],および [[=ê=]fg] は,それぞれ,[eéêfg] に相当します。 照合順序とその使用方法,および国際化機能の使用方法についての詳細は,『Tru64 UNIX ユーザーズ・ガイド』 を参照してください。

1.2    grep コマンドの使用

grep とは global regular expression printer の略です。egrep コマンドおよび fgrep コマンドの機能は,それぞれ grep -E および grep -F で実現されています。 これらのフラグを使用した場合の grep コマンドの動作について,表 1-3 で説明します。

表 1-3:  grep コマンドの動作

grep のバージョン 説明
grep 基本 (basic) grep。 パターンを基本正規表現として解釈します。
grep  -E (egrep) 拡張 (extended) grep。 パターンを拡張正規表現として解釈します。
grep -F (fgrep) 固定 (fixed) grep。 すべての正規表現演算子をリテラル文字として解釈します。

すべての形式の grep コマンドに対して,1 つ以上のパターンを複数行に渡って指定することができます。 この場合,次の Bourne シェルを使用した例のように,パターンをアポストロフィで囲み,改行文字で文字列を区分します。

$ strings hpcalc | grep -F 'math.h
> fatal.h'
 

C シェルの場合は,各改行文字の前にバックスラッシュを入力してください。

% strings hpcalc | grep -F 'math.h\
fatal.h'
 

また,-e フラグを使用して,複数のパターンを 1 行に指定することもできます。

% grep -e 'ab*c' -e 'de*f' myfile
 

省略時の設定では,grep コマンドは,指定したパターンを含む行をすべて検出します。表 1-4 に,検索時の動作を指定するための grep コマンドのオプションを示します。

表 1-4:  grep コマンドのオプション

フラグ 説明
-b 各出力行の先頭にディスク・ブロック番号を出力します。 このフラグは主に,特定のブロック内にある情報を検索することによって,プログラマがディスク上の特定ブロックを調べるために使用されます。
-c 指定したパターンが含まれる行の行数のみを出力します。
-e pattern_list pattern_list をパターンとして使用します。 複数のパターンを指定する場合は,改行で区切ります。pattern_list- で始まる場合に便利です。
-f pattern_file パターンをファイルによって指定します。pattern_file では,1 行に 1 つずつパターンを指定します。
-h 複数のファイルを処理している場合にファイル名を出力しません。
-l パターンを含むファイルのファイル名のみを表示します。 1 つのファイル内で複数行に渡ってパターンが存在する場合も,ファイル名は 1 回だけ表示します。 このフラグとともに,処理するファイルとして標準入力が指定されている場合,ファイル名の代わりに (standard input) というメッセージを出力します。
-n 各出力行の先頭に行番号を出力します。
-p paragraph_sep paragraph_sep をパラグラフ・セパレータとして使用し,一致した行を含むパラグラフ全体を出力します。 パラグラフ・セパレータ行は出力されません。 省略時のパラグラフ・セパレータは空白行です。
-q "quiet" モードで動作します。 エラー・メッセージ以外は何も出力しません。 [脚注 1]
-s ファイルが存在しない場合あるいはファイルに到達できないために発生するエラー・メッセージの出力を制限します。 その他のエラー・メッセージは出力されます。 [脚注 1]
-v 指定したパターンと一致しない行のみを出力します。
-w expr expr がテキスト中のワードとして検索された場合にのみその行を出力します。 ワードとは,句読点,ホワイト・スペースなどの英数字以外の文字で区切られた,(英字,数字,および下線で構成される) 英数文字列のことです。 たとえば,word1 は,ワードですが,A+B はワードではありません。
-x 行全体が一致する場合のみ出力します。
-y -i フラグと同じです。

正規表現の詳細については, grep(1) を参照してください。