移動先 先頭, , , 末尾 セクション, 目次.

正規表現

正規表現とは、文字列の集合を表現する方法である。 正規表現はawkプログラミングにおいて非常に基本的な 部分であるので、その書式と使い方は章を分けて説明するに値する。

スラッシュ(`/')に囲まれた正規表現は、その正規表現が示す集合に 属するテキストが含まれる全ての入力レコードにマッチするawkの パターンである。

もっとも単純な正規表現は、文字や数字、もしくはその両方の並びである。 このような正規表現はそのような並びを含む任意の文字列にマッチする。 したがって、`foo'という正規表現は`foo'を含む任意の文字列 にマッチすることになる。 それにより、/foo/というパターンはレコードのどこであっても `foo'という三文字を含む入力レコードにマッチすることになる のである。他の種類の正規表現は、あなたがより複雑な文字列の集合を指定でき るようにするものである。

Initially, the examples will be simple. As we explain more about how regular expressions work, we will present more complicated examples.

正規表現の使い方

正規表現はスラッシュで囲まれたパターンとして使うことができる。そのような正 規表現は各レコードのテキスト全体に対してのテストが行われる。(通常は、成功 かどうかを決めるにはテキストの一部分だけ見れば良い)以下に挙げる例は`foo' を含むレコードの第二フィールドを出力する。

$ awk '/foo/ { print $2 }' BBS-list
-| 555-1234
-| 555-6699
-| 555-6480
-| 555-2127

正規表現はまた、マッチング式として使うことができる。これらの式は マッチングを試みる文字列を特定することを許し、カレント入力レコード 全体とマッチングすることをしないで済むようにできる。 `~'`!~'という二つの演算子は正規表現の比較をおこなう。 これらの演算子を使った式はパターンとしてや使ったり、ifwhilefordo文中で使うこととができる。

exp ~ /regexp/
これはexp(文字として扱われる)という式がregexpとマッチする ときに真となる。以下に挙げる例は、第一フィールドに大文字の`J' を含んでいる入力レコードをすべて選択するものである。
$ awk '$1 ~ /J/' inventory-shipped
-| Jan  13  25  15 115
-| Jun  31  42  75 492
-| Jul  24  34  67 436
-| Jan  21  36  64 620
こう書いても良い。
awk '{ if ($1 ~ /J/) print }' inventory-shipped
exp !~ /regexp/
これはexp(文字列として扱われる)という式がregexpマッチしないときに真となる。次に挙げる例では、最初のフィールドに 大文字の`J'含まない入力レコードすべてを選択する。
$ awk '$1 !~ /J/' inventory-shipped
-| Feb  15  32  24 226
-| Mar  15  24  34 228
-| Apr  31  52  63 420
-| May  16  34  29 208
...

正規表現が/foo/のようにスラッシュで囲まれて記述されたとき、 これを正規表現定数と呼ぶ。これは5.27のような数値定数や "foo"のような文字列定数のようなものである。

エスケープシーケンス

一部のキャラクタは("foo")のような文字列定数やregexp constants ( code{/foo/})のような正規表現定数にそのままの形で含める事ができない。このよ うなキャラクタは、キャラクタそのものではなくバックスラッシュ(`\'で始 まるエスケープシーケンス)を代わりに使うことで文字列などに含めること ができる。

エスケープシーケンスの一つの用途は文字列定数に二重引用符を含めるためである。 生の二重引用符は文字列の終端になってしまうため、それが二重引用符のキャラク タそのものであることを明示するために`\"'を使わなければならない。例を 挙げよう。

$ awk 'BEGIN { print "He said \"hi!\" to her." }'
-| He said "hi!" to her.

バックスラッシュキャラクタそれ自身は、そのまま含むことのできないキャラク タである。文字列や正規表現中にバックスラッシュを一つ含めるには、`\\' と記述する。したがって、`"'`\'という二つのキャラクタからな る文字列は"\"\\"と記述しなければならない。

もう一つのバックスラッシュの用途は、タブとか改行のような非印字キャラクタ (unprintable characters)を表すためのものである。非印字キャラクタをそのま ま文字列定数や正規表現定数に含めてしまうと多分見づらくなってしまう。

以下にawkで使われる全てのエスケープシーケンスを挙げる。 特に断りがない限り、これらのエスケープシーケンス全ては文字列定数と 正規表現定数の両方に適用される。

\\
A literal backslash, `\'. `\'そのもの。
\a
"警告"キャラクタ。Control-gであり、ASCIIコードの7(BEL)。
\b
後退。Control-hであり、ASCIIコードの8(BS)。
\f
改ページ。Control-l, ASCIIコードの12 (FF)。
\n
改行。Control-j, ASCIIコードの10 (LF)。
\r
復帰。Control-m, ASCIIコードの13 (CR)。
\t
水平タブ。 Control-i, ASCIIコードの 9 (HT)。
\v
Vertical tab, Control-k, ASCII code 11 (VT). 垂直タブ。 Control-k, ASCIIコードの11 (VT)。
\nnn
八進数値nnnの値。nnn`0'から`7'までの数字の 一つから三つの並び。ASCIIのESC(エスケープ)キャラクタのコードは `\033'である。
\xhh...
十六進数値hhの値。hhは十六進文字(`0'から`9' までと、`A'から`F'もしくは`a'から`f')。ANSI Cと同様に、 最初の非十六進文字が見つかるまでエスケープシーケンスは連続しているものとみ なされる。しかしながら、二文字を越える十六進文字列はどのような結果になるか は未定義である(`\x'エスケープシーケンスはPOSIXのawkでは許され ていない)。
\/
文字としてのスラッシュ(正規表現定数に対してのみ必要)。これはスラッシュを正 規表現定数に含めたいときに使用する。正規表現がスラッシュで終端するので、 awkに残りの正規表現を処理し続けるのを指示するのにエスケープしてスラ ッシュをパターンの一部にする必要がある。
\"
二重引用符そのもの(文字列定数に対してのみ必要)。これは二重引用符を文字列 定数に含めたいときに使用する。文字列が二重引用符で終端するので、文字列の残 りをawkに処理し続けるのを指示するのにエスケープしてスラッシュを文字 列の一部にする必要がある。

gawkでは、正規表現中で特別な意味を持つバックスラッシュで始まる二文字の エスケープシーケンスが幾つか追加されている。 セクション gawkでのみ使える正規表現演算子を参照.

文字列定数中で、上の一覧にないキャラクタの前にバックスラッシュを 置いた場合にはなにがおこるのだろうか? POSIXでは故意にそれが定義されていない。ここでは二つの選択肢がある。

正規表現中に上の一覧にないキャラクタや、 セクション gawkでのみ使える正規表現演算子を参照 にリストアップされていないキャラクタの前にバックスラッシュがある場合、 それが通常は正規表現演算子として扱われるものであったとしても、 そのキャラクタをその文字そのものとみなす。 一例を挙げると、/a\+b/`a+b'という三文字にマッチする。

移植性を完全なものとするには、先に挙げたキャラクタ以外のキャラクタの 前にバックスラッシュを置かないようにすること。

もう一つ、興味深い疑問がある。八進や十六進のエスケープを使用して 正規表現のメタキャラクタを表すシーケンスを記述したとき、 (セクション 正規表現演算子を参照). awkはそのようなキャラクタを文字として見るのだろうか? それとも正規表現の演算子と見るのだろうか?

このようなキャラクタは伝統的にその文字そのものとして扱われる(d.c.)。 しかし、POSIX標準ではこれはメタキャラクタであるかのように扱うよう指示さ れており、gawkの振る舞いもそうなっている。ただし互換モード (セクション コマンドラインオプションを参照)では、gawkは正規表現定数中で八進 や十六進のエスケープシーケンスによって表現されたキャラクタは文字そのもの として扱われる。したがって、/a\52b//a\*b/と等価である。

まとめ

  1. 前述の一覧にあるエスケープシーケンスは、文字列定数でも、正規表現定数で も常に最初に処理される。これは非常に早い段階、awkがプログラムを 読み込んだときに行われる。
  2. gawkは正規表現定数、動的正規表現 (セクション 動的正規表現を使うを参照)の両方で、 セクション gawkでのみ使える正規表現演算子を参照. で述べられているような特殊な演算子を処理する。
  3. バックスラッシュを任意のキャラクタの前に置くことは、そのキャラクタを文 字そのものとして扱うことを意味している。

正規表現演算子

以下に挙げるような正規表現演算子とかメタキャラクタと呼ばれる 正規表現の記述力を増加させるようなキャラクタを使って、 正規表現式を組み合わせることができる。

先にセクション エスケープシーケンスを参照で述べたエスケープシーケンスは 正規表現の中でも使うことができて、それらは先頭に`\'が置かれている。 正規表現の処理に先立って、 このようなエスケープシーケンスは解析されて、そのシーケンスの表す キャラクタに置きかえられる。

以下はメタキャラクタの一覧である。 エスケープシーケンスではなくこの一覧にないキャラクタはすべて、 それ自身を表すキャラクタである。

\
これはマッチングのときに あるキャラクタの特殊な意味を抑制するために使用する。 例えば、
\$
`$'というキャラクタにマッチする。 @cindex regexp, anchors
^
これは文字列の先頭にマッチする。 例えば、
^@chapter
は文字列の先頭にある`@chapter'にマッチする。これは Texinfoファイルで章の先頭を見つけるのに使用できる。 `^'は文字列の先頭部分にのみマッチさせるのに使う 目印であるので、アンカー(anchor)として知られる。 `^'は 文字列中にある行(line embedded in a string)の 先頭にはマッチしないことに注意。次の例の条件式は真にはならない。
if ("line1\nLINE 2" ~ /^L/) ...
$
これは`^'に似ているが、文字列の最後にマッチする。 例えば、
p$
これは`p'で終わるレコードにマッチする。`$'もアンカーであり、 文字列中の行末にはマッチしない。例えば、
if ("line1\nLINE 2" ~ /1$/) ...
この条件は真にはならない。
.
ピリオド、あるいはドットは改行を含む、任意のキャラクタにマッチ する。例えば、
.P
これは`P'が後に続く任意の一文字にマッチする。連接を使うことによっ て、`U.A'のような`U'で始まり`A'で終わる任意の三文字の並 びにマッチするような正規表現を作ることができる。 厳密なPOSIXモード(セクション コマンドラインオプションを参照)では、 `.'はすべてのビットが0であるキャラクタ、NULにはマッチしない。 しかしながら、NULは単にもう一つのキャラクタである。 他のバージョンのawkでは、NULキャラクタには マッチさせることができない。
[...]
これはキャラクタリスト(character list)と呼ばれるものである。 これはブラケットに囲まれているキャラクタのいずれか一つと マッチする。例えば、
[MVX]
これは文字列中にある`M', `V', `X'のいずれかの キャラクタとマッチする。 キャラクタの範囲を、範囲の始点と終点の間にハイフンを置き、 全体をブラケットに囲まれた中に置くことで 指示することができる。
[0-9]
これは任意の数字にマッチする。 "すべてのアルファベットと数字"を表す常識的な考えである [A-Za-z0-9] のように複数の範囲を使うこともできる。 `\', `]', `-', `^' といったキャラクタを キャラクタリストの中に含めるには、そのキャラクタの前に`\'を つける。例えば、
[d\]]
これは`d'`]'にマッチする。 このキャラクタリスト中の`\'の扱いは、他のawk処理系と共通であ り、これはPOSIXの定めるところでもある。awkにおける正規表現はPOSIX で規定されている拡張正規表現(Extended Regular Expressions, EREs)のスーパ ーセットである。POSIXの拡張正規表現は伝統的なegrepユーティリティ が受け付ける正規表現に基づいている。 キャラクタクラスはPOSIX標準により導入された新しい機能である。 キャラクタクラスは(特定の属性を持つ) キャラクタのリストを表す特殊な記述であるが、表現されるキャラクタ 自身が国ごと、あるいはキャラクタセットごとに異なるものとなる可能性がある。 例を挙げると、USAでいうところのアルファベットとフランスのアルファベット では異なるものとなるということである。 キャラクタクラスは、キャラクタリストを囲むブラケットの内側 でのみ有効である。キャラクタクラスは`[:'、クラスを区別するキーワード、 `:]'から構成される。以下はPOSIX標準で定義されているキャラクタクラス の一覧である。
[:alnum:]
アルファベットと数字。
[:alpha:]
アルファベット。
[:blank:]
スペースとタブ。
[:cntrl:]
コントロールコード。
[:digit:]
十進数字。
[:graph:]
印字可能かつ表示可能な文字 (スペースは印字可能だが表示不可。`a'は両方とも可)。
[:lower:]
アルファベットの小文字。
[:print:]
印字可能なキャラクタ(コントロールコードでないキャラクタ)
[:punct:]
句読点(通常の文字や数字、制御文字、スペースキャラクタのいずれでも ないもの)。
[:space:]
スペースキャラクタ(スぺース、タブ、改ページ)
[:upper:]
アルファベットの大文字。
[:xdigit:]
十六進の数字。
POSIXの標準以前では、アルファベットか数字にマッチさせるには /[A-Za-z0-9]/と書かなければならなかった。もし、使用する環境のキャ ラクタセット が、元のものとは違うものであった場合、これはマッチしなくなっ てしまうだろう。POSIXのキャラクタセットを使うことで/[[:alnum:]]/の ように記述 ができ、かつこれはすべてのキャラクタセットにおいて、アル ファベッ トか数字にマッチするのである。 キャラクタリスト中に更に二つの特殊なシーケンスを置くことができる。 これらは、一文字以上の長さを持つ一つのシンボルを持つことのできるような 非ASCIIキャラクタセットに適用して、通常のキャラクタと同じように 照合やソートなどを行うようにするためのものである(例えばフランス語 では"e"はアクサングラーブの付いた"`e" と等価である)。
Collating Symbols
照合シンボル(collating symbol)は、`[.'`.]'の間に置かれた マルチキャラクタの照合要素である。例えば、`ch'が照合要素 だったすると、[[.ch.]]はこの照合要素にマッチする正規表現であるが、 [ch]`c'`h'にマッチする正規表現である。
Equivalence Classes
等価クラス(equivalence class)は `[='`=]'の間にある等価なロカール固有のキャラクタのリストである。 したがって、[[=e=]]`e'`'e'``e'にマッチする正規表現である。
これらの機能は、非英語圏のロカールにおいて非常に有効である。 警告: 現在gawkが使っている正規表現マッチングライブラリ の関数は、POSIXキャラクタクラスのみを認識し、照合シンボルや等価クラス を認識しない。
[^ ...]
これはキャラクタリストの補集合である。`['の直後のキャラクタは `^'なければならない。これはブラケットの中にあるキャラクタ 以外の任意のキャラクタにマッチする。例えば、
[^0-9]
これは数字でない任意のキャラクタにマッチする。
|
これは選択演算子であり、選択を行うのに使用する。 たとえば、
^P|[0-9]
この例は`^P'`[0-9]'で始まる文字列にマッチする。 これは`P'か数値で始まる文字列にマッチするということである。 選択は演算子の左右のそれぞれで、可能な限り大きな正規表現に適用される。 言い換えるなら、`|'は正規表現演算子の中で最低の優先順位である ということである。
(...)
括弧は正規表現を(算術式のときと同じ様にグループとする為に使用される。これ は選択演算子`|'を含んだ正規表現を連結する為に使う事ができる。 たとえば、`@(samp|code)\{[^}]+\}'`@code{foo}'にも`@samp{bar}'にもマッチする (これはTexinfoのフォーマット制御シーケンスである)。
*
このシンボルはその前に置かれている正規表現の必要な限りのくり返しにマッチ する。例えば
ph*
ここで`*'はその前にある`h'に適用され、一文字の`p'に続いて任意 の数の`h'がある文字列にマッチする。これは`p'だけで`h'が一個も ないようなパターンにもマッチする。 `*'のくり返しは、可能なかぎり最も小さな式が採用される。 (もしより大きな 式を繰り返したいのならば括弧を使えばよい) そしてその式は可能な限り大きなくり 返しを見つけだす。例えば、
awk '/\(c[ad][ad]*r x\)/ { print }' sample
`sample'中のレコードのうち、`(car x)', `(cdr x)', `(cadr x)'のような文字列を含むものを全て出力する。カッコの前にバッ クスラッシュをつけてエスケープしていることに注意。
+
このシンボルは`*'と似ているが、先行する部分正規表現が少なくとも一 回マッチしなければならない。つまり、
wh+y
この例でいうと、`wh*y'ではすべてマッチしていた`why'`whhy'`wy'のうち、前者二者にはマッチするが、最後のものにはマ ッチしないということである。次の例は、`*'で最後に挙げた例を書き直し たものである。
awk '/\(c[ad]+r x\)/ { print }' sample
?
このシンボルは`*'と似ているが、先行する部分正規表現が ないか、一回だけのときにマッチする。例を挙げると
fe?d
これは`fed'`fd'にマッチするが、それ以外にはマッチしない。
{n}
{n,}
{n,m}
interval expresionの ブレースの内側には、一つか二つの数値がある。もしブレースの中に数値が一つ だけならば、直前の正規表現がn回繰り返される。もしカンマに区切られ て数値が二つあれば、直前の正規表現がn回からm回繰り返される。 カンマの後ろに数値が一つだけならば、直前の正規表現が少なくともn回 繰り返される。
wh{3}y
これは`whhhy' にマッチするが、 `why'`whhhhy'には マッチしない。
wh{3,5}y
これは `whhhy'`whhhhy'`whhhhhy'の いずれかのみにマッチする。
wh{2,}y
`whhy'`whhhy'などにマッチする。
Interval expressionsは伝統的なawkでは使えなかった。 POSIX標準の一部として、 awkegrepとほかのユーティリティとの 一貫性のため、これが追加された。 しかしながら、古いプログラムでは`{'`}'を正規表現定数の中で 使っているかもしれないので、gawkはデフォルトでは正規表現中の interval expressionsはマッチしない`--posix'オプションか `--re-interval'オプション(セクション コマンドラインオプションを参照) が指定されると、interval expressionsを正規表現として使うことができるよう になる。

正規表現では、`*', `+', `?'といった演算子は`{'`}'と同じ優先順位を持ち、その上に連接があり、下には`|'がある。 算術式と同じように、カッコはそれで括った演算子の優先順位を変更することが できる。

gawkが互換モード(セクション コマンドラインオプションを参照)で 動作している場合、キャラクタクラスとinterval expressionは 正規表現中で使うことができない。

The next 次の section セクションでは GNU特有の正規表現演算子について述べる。 さらに、gawkが正規表現キャラクタを解釈する 方法に影響するコマンドラインオプションについて 詳しく説明する。

gawkでのみ使える正規表現演算子

GNUのソフトウェアは、幾つかの正規表現演算子を追加した正規表現を提供して いる。このセクションで説明されるこれらの演算子はgawk特有の ものであり、他のawkの処理系では使用できないものである。

追加されている演算子のほとんどは、単語のマッチングに関係したものである。 ここで、単語とは一文字以上の、文字、数字、アンダースコア(`_') の並びである。

\w
これは単語を構成する任意のキャラクタ、つまり 文字、数字、それとアンダースコアにマッチする演算子である。 これは [[:alnum:]_] の簡潔な表現とみなして良い。
\W
これは単語を構成する要素にならない任意のキャラクタにマッチする 演算子である。これは [^[:alnum:]_] の簡潔な表現とみなして良い。
\<
これは単語の先頭にある空文字列にマッチする演算子である。 例えば、/\<away/`away'にマッチするが、 `stowaway'にはマッチしない。
\>
これは単語の末尾にある空文字列にマッチする演算子である。 例えば、/stow\>/`stow'にマッチするが、 `stowaway'にはマッチしない。
\y
これは単語の先頭、あるいは末尾の空文字列とマッチする演算子である (つまり語の区切りとマッチするということである)。 例えば、`\yballs?\y'は独立した単語として `ball' にも `balls'にもマッチする。
\B
この演算子は単語中の空文字列にマッチする。言い換えると、`\B'は二つ の単語の構成要素文字の間にある空文字列にマッチするということである。例え ば、/\Brat\B/`crate'にマッチする。しかし、`dirty rat' にはマッチしない。`B'は簡単にいうと`\y'の反対語である。

さらに二つのバッファ上で動作する演算子がある。Emacsでは、バッファ はEmacsのバッファのことである。他のプログラムでは、gawkが使用し ている正規表現ライブラリは文字列全体をバッファにあたるものとしている。

awkにおいては、`^'`$'は常に文字列の先頭や末尾に働く ので、これらの演算子は新しい機能をもたらすものではない。これらは他の GNUソフトウェアとの互換性のために提供されている。

\`
この演算子はバッファの先頭にある空文字列にマッチする。
\'
この演算子はバッファの末尾にある空文字列にマッチする。

他のGNUソフトウェアでは、語の区切り演算子は`\b'である。 しかしながら、これはawk言語では バックスペースがすでに`\b'と定義されているので衝突してしまう。 そこで、gawkでは違う演算子を使っているのである。

ある別のやり方でGNU特有の演算子では二つのバックスラッシュを 要求するというものがあったが、これは混乱を招くと考えられたので 現在の方法の、`\y'をGNUの`\b'として扱うほうが ちょっとばかしましである。

gawkが正規表現中のキャラクタをどのように解釈するかを 制御するためのコマンドラインオプション(セクション コマンドラインオプションを参照) が幾つかある。

No options
デフォルトでは、gawkは above. 前述した POSIXの正規表現と、GNUの正規表現演算子のすべての機能を 提供する。ただし、interval expressionはサポートしない。
--posix
POSIXの正規表現のみをサポートする。GNUの演算子は特殊なものではなく(例え ば`\w'`w'という文字そのものにマッチする)、interval expressionを使うことができる。
--traditional
伝統的なUNIXawkの正規表現がマッチする。GNUの演算子は特別でなく、 interval expressionとPOSIXのキャラクタクラス([[:alnum:]]など)も使 用不可である。八進や十六進のエスケープシーケンスで表わされたキャラクタは、 それが正規表現のメタキャラクタであってもキャラクタそのものとして扱われる。
--re-interval
正規表現中でinterval expressionを使うことを許可する。 これは`--traditional'が指定されているときも有効である。

大小文字を区別するマッチング

大小文字は通常正規表現の中では通常のキャラクタマッチのとき(メタキャラクタを除 く)でも、キャラクタセットの内側のときでも区別される。したがって、正規表現中 の`w'は小文字の`w'とだけマッチして大文字の`W'とはマッチしない。

大小文字を無視してマッチを行う最も単純な方法はキャラクタセットを使って `[Ww]'の様にすることである。しかし、これは正規表現を読みにくいものとし てしまう。他に取るべき手段としては二つある。

プログラム中の任意の点で大小文字に関係なくマッチングを行うための手段の一つは、 データをtolowertoupperという組み込みの文字列処理関数(まだ これらの関数の説明はされていない)を使用して、大文字、小文字どちらかに揃えて しまうというものである。(tolower 及びtoupperの詳しい説明は、 セクション Built-in Functions for String Manipulationを参照). たとえば

tolower($1) ~ /foo/  { ... }

この例ではマッチングを行なう前に、最初のフィールドを小文字に変換している。

もう一つの、gawkに特有な方法は、変数 IGNORECASE(セクション 組み込み変数を参照) に非0の値をセットすることであり、これによってすべての 正規表現演算、文字列演算で大小文字が無視される。 IGNROECSEは他の大部分の変数と同様に ゼロで初期化されているので、デフォルトでは大小文字は 区別される。

x = "aB"
if (x ~ /ab/) ...   # このテストは失敗する

IGNORECASE = 1
if (x ~ /ab/) ...   # 今度は成功する

一般的にはIGNORECASEを特定のルールをcase-insensitive(大小文字を区 別しない)にしたり、case-sensitive(大小文字を区別する)ようにするために使 うことはできない。それは、特定のルールのパターンのためにIGNORECASE をセットする方法がないからである。 これを行うには、キャラクタクラスを使うか、tolowerを使うか しなければならない。しかし、IGNORECASEを すべてのルールに対して、動的にオンにしたりオフにしたりすることは できる。

IGNORECASEはコマンドラインででも、BEGINルール中で でもセットすることができる (セクション Other Command Line Argumentsを参照と セクション Startup and Cleanup Actionsを参照)。 コマンドラインでIGNORECASEの設定をすることによって、 プログラムを編集することなしに 大小文字を区別しないものにすることができる。

バージョン3.0以前のgawkでは、IGNORECASEの 値は正規表現演算にのみ影響していて、`=='`!='などを 使った文字列比較などには影響しなかった。 バージョン3.0からは、IGNORECASEの値は 正規表現演算と文字列比較の両方に影響するようになった。

gawkのバージョン3.0から、大小文字の間の等価性(equivalence)は ISO-8859-1(ISO Latin-1)キャラクタセットに基づくものとなった。 このキャラクタセットは伝統的な128 ASCIIキャラクタセットのスーパーセット であり、ヨーロッパ諸国の言語で使用するのに適当なキャラクをいくつか 提供するものである。

IGNORECASEの値はgawkが互換モード (セクション コマンドラインオプションを参照)のときには何の効果も持たない。 互換モードでは大小文字の区別は常に行われる。

How Much Text Matches?

以下の例について考えてみよう。

echo aaaabcd | awk '{ sub(/a+/, "<A>"); print }'

これはsub関数(まだこれは説明していない。 セクション Built-in Functions for String Manipulationを参照) を使って入力レコードを変更する例である。ここで、/a+/という 正規表現は"一つ以上の`a'"を表しており、それにマッチする テキストを`<A>'に置き換えるというものである。

入力には四つの`a'がある。出力はどうなるだろうか?言い換えれば、"一 つ以上"とは幾つなのか、awk`a'二つにマッチさせるのか、それ とも三つなのか、あるいは四つ全てにマッチさせるのかということである。

答えを言うと、awk(とPOSIX)の正規表現は、常にマッチするもののうち 最も左にあり、最も長いキャラクタの並びにマッチする (最左最長一致)。したがって、 この例では四つの連続した`a'が(一つの)`<A>'に置き換えられる。

$ echo aaaabcd | awk '{ sub(/a+/, "<A>"); print }'
-| <A>bcd

単純にマッチする/しないをテストするときには今述べた事は さして重要ではない。しかし、正規表現に基づいたフィールドやレコードの 分割、そしてmatch, sub, gsub,gensub といった関数を使用してテキストのマッチングや置き換えをする場合には 非常に重要である。 この原則を理解する事は正規表現に基づいたレコード/フィールドの 分割のためにも重要である(セクション 入力をレコードへと分割をするやりかたを参照, と セクション フィールドの分割方法の指定を参照)。

動的正規表現を使う

`~'演算子や`!~'演算子の右辺に置くものは正規表現定数(スラッシュの間に置 かれた文字列)である必要はなく、任意の式を置くことができる。そのような式 は評価され、必要があれば文字列に変換される。評価され変換が行なわれた 結果は正規表現として扱われる。 このように演算が行われる正規表現は動的正規表現(dynamic regular expression)と呼ばれる。例を挙げよう。

BEGIN { identifier_regexp = "[A-Za-z_][A-Za-z_0-9]+" }
$0 ~ identifier_regexp    { print }

これはidentifier_regexpawkでの変数名を表す正規表現をセ ットし、入力レコード中にこの正規表現にマッチするものがあるかをテストす るものである。

警告:`~'演算子や`!~'演算子を使った場合、スラッシュで 囲まれた正規表現定数と二重引用符で囲まれた文字列定数とでは違いがある。文 字列定数を使おうとする場合、文字列が二度走査されることを理解する 必要がある。一度目はawkがプログラムを読み込んだとき、二度目は演算 子の左側に置かれた文字列と右側のパターンとのマッチングを行うときである。 これは式として評価される(先の例で言う identifier_regexpのように) 任意の文字列において真であり、文字列定数そのものにはあてはまらない。

文字列が二度走査されることによる違いとはなんだろうか? その答えは、エスケープシーケンス、特にバックスラシュの振る舞いにある。 正規表現を通して文字列中にあるバックスラッシュを得るには、 二つのバックスラッシュを置かなければならない。

例えば、/\*/*という文字にマッチする正規表現定数であり、 これはバックスラッシュ一つを必要とする。同じものを文字列を使って行う には、"\\*"としなければならないだろう。最初のバックスラッシュは 二個めのバックスラッシュをエスケープするものであり、これによってこの文 字列は`\'`*'という二つのキャラクタからなる文字列となる。

正規表現を記述するのに正規表現定数と文字列定数の両方が使えるとき、どち らを使ったほうが良いのだろうか? その答えは"正規表現定数"である。以下 にその理由を挙げる。

  1. 文字列定数のほうが記述するのに面倒であり、また読みにくい。正規表現定数を 使うことはエラーを招きにくくする。これら二種類の定数の違いを理解しないこ とはエラーの発生源である。
  2. 正規表現定数を使ったほうが効率が良い。そうすることでawkはあなたが 記述した正規表現に注意することができ、そしてそれをより効果的にパターンマ ッチングするための内部的な表現で格納する事ができるようになる。文字列定数 を使った場合、awkはまず初めに文字列を内部表現に変換しなければなら ず、その後でパターンマッチングを行う。
  3. 正規表現定数を使ったほうが良いスタイルであり、そのほうが正規表現のマッチ で何をさせようとしているかが明確になる。

移動先 先頭, , , 末尾 セクション, 目次.