Main Content

正規表現

このトピックでは、正規表現とは何か、そしてそれを使用してテキストを検索する方法について説明します。正規表現は柔軟で強力ですが、複雑な構文を使用します。正規表現の代替方法にpattern("R2020b" 以降) があり、これは定義がより簡単で、コードが読みやすくなります。詳細については、パターン表現の作成を参照してください。

正規表現とは

正規表現は、特定のパターンを定義する一連の文字です。通常、プログラム入力の解析やテキスト ブロックの処理を行う際などに、テキスト内でパターンに一致する単語のグループを検索するのに使用します。

文字ベクトル 'Joh?n\w*' は正規表現の一例です。この文字列は Jo で始まり、オプションで h ('h?' で示される部分) が続き、次に n が続き、任意の数の "単語文字" (アルファベット、数字またはアンダースコア。'\w*' で示される部分) で終わるパターンを定義しています。このパターンは、次のすべてに一致します。

Jon, John, Jonathan, Johnny

正規表現は、テキスト内で特定の文字のサブセットを検索する特殊な方法です。strfind などの関数で行うように、完全に一致する文字を探す代わりに、正規表現では、文字の特定の "パターン" を検索できます。

たとえば、メートル法の速度を表現する方法には以下があります。

km/h
km/hr
km/hour
kilometers/hour
kilometers per hour

5 つの別々の検索コマンドを発行することで、テキスト内で上述の用語を見つけることができます。

strfind(text, 'km/h');
strfind(text, 'km/hour');
% etc.

しかし、さらに効率的な方法は、これらすべての検索用語に適用できる 1 つのフレーズを作成することです。

Flow-chart describing logic of example regular expression.

このフレーズを正規表現に変換すると (この節で後述)、次のようになります。

pattern = 'k(ilo)?m(eters)?(/|\sper\s)h(r|our)?';

これで、1 つのコマンドのみを使用して 1 つ以上の用語を見つけます。

text = ['The high-speed train traveled at 250 ', ...
   'kilometers per hour alongside the automobile ', ...
   'travelling at 120 km/h.'];
regexp(text, pattern, 'match')
ans =

  1×2 cell array

    {'kilometers per hour'}    {'km/h'}

正規表現による文字の検索と置換をサポートする MATLAB® 関数は、4 つあります。最初の 3 つは、受け入れる入力値、および返す出力値が同様です。詳細については、関数リファレンス ページのリンクをクリックしてください。

関数説明
regexp

正規表現と一致

regexpi

大文字小文字を区別しない、正規表現の一致

regexprep

正規表現を使用したテキストの一部の置き換え

regexptranslate

テキストを正規表現に変換

最初の 3 つの関数のどれを呼び出す場合も、解析するテキストと正規表現を最初の 2 つの入力引数で渡します。regexprep を呼び出す場合は、置換のパターンを指定する式を追加の入力として渡します。

式の作成手順

テキストで特定の用語を検索するために正規表現を使用するには次の 3 つ手順に従います。

  1. 文字列に固有のパターンを識別する

    これを行うには、検索するテキストを類似した文字タイプのグループに分解します。これらの文字タイプには、一連の小文字、ドル記号の後に続く 3 つの数字と小数点などがあります。

  2. 正規表現として各パターンを表現する

    このドキュメンテーションで説明されている "メタ文字" と演算子を使用して、検索パターンの各セグメントを正規表現で表現します。次にそれらの表現セグメントを組み合わせて単一の表現にし、検索で使用します。

  3. 適切な検索関数を呼び出す

    解析するテキストを regexpregexpi などの検索関数の 1 つ、またはテキスト置換関数 regexprep に渡します。

この節で示す例では、友達 5 人のグループに所属する連絡先情報を含むレコードを検索します。この情報には、各自の名前、電話番号、居住地、電子メール アドレスが含まれます。目的は、テキストから特定の情報を抽出することです。

contacts = { ...
'Harry  287-625-7315  Columbus, OH  hparker@hmail.com'; ...
'Janice  529-882-1759  Fresno, CA  jan_stephens@horizon.net'; ...
'Mike  793-136-0975  Richmond, VA  sue_and_mike@hmail.net'; ...
'Nadine  648-427-9947  Tampa, FL  nadine_berry@horizon.net'; ...
'Jason  697-336-7728  Montrose, CO  jason_blake@mymail.com'};

例の最初の部分では、標準の電子メール アドレスの形式を表す正規表現を作成します。この表現を使用して、友達のグループの 1 人の電子メール アドレス情報を検索します。Janice の連絡先情報は cell 配列 contacts の 2 行目にあります。

contacts{2}
ans =

    'Janice  529-882-1759  Fresno, CA  jan_stephens@horizon.net'

手順 1 — テキストに固有のパターンを識別する

一般的な電子メール アドレスは次の標準的な構成要素から構成されます。ユーザーのアカウント名に続き、@ 記号、ユーザーの ISP (インターネット サービス プロバイダー) の名前、ドット (ピリオド)、ISP が属するドメインで構成されます。次の表では、左の列にこれらのコンポーネントを、右の欄に各コンポーネントの形式を一般化してまとめています。

電子メール アドレスに固有のパターン各パターンの一般的な説明
アカウント名で始まる
jan_stephens . . .
1 つ以上の小文字とアンダースコア
'@' を追加する
jan_stephens@ . . .
@ 記号
ISP を追加する
jan_stephens@horizon . . .
1 つ以上の小文字。アンダースコアなし
ドット (ピリオド) を追加する
jan_stephens@horizon. . . .
ドット (ピリオド) 文字
ドメインで終わる
jan_stephens@horizon.net
com または net

手順 2 — 正規表現として各パターンを表現する

この手順では、手順 1 で作成した一般的な形式を正規表現のセグメントに変換します。次にそれらのセグメントを結合して表現全体を形成します。

次の表では、左の欄に一般化した形式の説明をまとめています(これは、手順 1 の表の右の欄から取り込んだものです)。2 番目の欄は、文字パターンを表す演算子またはメタ文字を示しています。

各セグメントの説明パターン
1 つ以上の小文字とアンダースコア[a-z_]+
@ 記号@
1 つ以上の小文字。アンダースコアなし[a-z]+
ドット (ピリオド) 文字\.
com または net(com|net)

これらのパターンを 1 つの文字ベクトルに組み立てて、次のような式を完成します。

email = '[a-z_]+@[a-z]+\.(com|net)';

手順 3 — 適切な検索関数を呼び出す

この手順では、手順 2 で作成した正規表現を使用して、グループに属する友達の 1 人の電子メール アドレスを一致させます。この検索は、関数 regexp を使用して行います。

この節で前述した連絡先情報のリストは次のとおりです。各メンバーのレコードは、cell 配列 contacts の 1 行を占めています。

contacts = { ...
'Harry  287-625-7315  Columbus, OH  hparker@hmail.com'; ...
'Janice  529-882-1759  Fresno, CA  jan_stephens@horizon.net'; ...
'Mike  793-136-0975  Richmond, VA  sue_and_mike@hmail.net'; ...
'Nadine  648-427-9947  Tampa, FL  nadine_berry@horizon.net'; ...
'Jason  697-336-7728  Montrose, CO  jason_blake@mymail.com'};

次に手順 2 で作成した電子メール アドレスを表す正規表現を示します。

email = '[a-z_]+@[a-z]+\.(com|net)';

関数 regexp を呼び出し、cell 配列 contacts の 2 行目と正規表現 email を渡すと、Janice の電子メール アドレスが返されます。

regexp(contacts{2}, email, 'match')
ans =

  1×1 cell array

    {'jan_stephens@horizon.net'}

MATLAB では、文字ベクトルは左から右へと解析され、解析の進行と同時にベクトルが処理済みになっていきます。一致する文字が見つかると、regexp でその場所が記録され、最後に一致した文字の直後から文字ベクトルの解析が再開されます。

今度はリストの 5 番目のメンバーについて同じ呼び出しを行います。

regexp(contacts{5}, email, 'match')
ans =

  1×1 cell array

    {'jason_blake@mymail.com'}

さらに、入力引数の cell 配列全体を使用すると、リスト内の全員の電子メール アドレスを検索することもできます。

regexp(contacts, email, 'match');

演算子と文字

以下の節で説明があるように、正規表現には、一致するパターンを指定する文字、メタ文字、演算子、トークンおよびフラグを含めることができます。

メタ文字

メタ文字は、文字、文字の範囲、数字および空白文字を表します。メタ文字を使用して文字の汎用パターンを構築します。

メタ文字

説明

.

空白を含む任意の単一文字

'..ain' は、'ain' で終わる 5 つの連続する文字のシーケンスと一致します。

[c1c2c3]

大かっこ内の任意の文字。次の文字は文字どおり扱われます。$ | . * + ? および - (範囲を示すために使用する場合を除く)。

'[rp.]ain''rain''pain' または '.ain' と一致します。

[^c1c2c3]

大かっこ内を除く任意の文字。次の文字は文字どおり扱われます。$ | . * + ? および - (範囲を示すために使用する場合を除く)。

'[^*rp]ain''ain' で終わる 4 文字のシーケンスと一致します。ただし、'rain''pain' および '*ain' は除きます。たとえば、'gain''lain' または 'vain' と一致します。

[c1-c2]

c1c2 の範囲の任意の文字

'[A-G]' は、AG の範囲の 1 文字と一致します。

\w

アルファベット、数字またはアンダースコア文字。英語の文字セットでは、\w[a-zA-Z_0-9] と等価です。

'\w*' は、アルファベット、数字またはアンダースコアの任意の文字のまとまりで構成される単語を識別します。

\W

アルファベット、数字またはアンダースコア以外の任意の文字。英語の文字セットでは、\W[^a-zA-Z_0-9] と等価です。

'\W*' は、アルファベット、数字またはアンダースコア以外の任意の文字のまとまりで構成される単語を識別します。

\s

任意の空白文字。[ \f\n\r\t\v] と等価です。

'\w*n\s' は後ろに空白文字が続く、文字 n で終わる単語と一致します。

\S

任意の空白文字以外の文字。[^ \f\n\r\t\v] と等価です。

'\d\S' は後ろに空白文字以外の文字が続く数字と一致します。

\d

任意の数字。[0-9] と等価です。

'\d*' は任意の数の連続する数字と一致します。

\D

任意の数字以外の文字。[^0-9] と等価です。

'\w*\D\>' は数字で終わらない単語と一致します。

\oN または \o{N}

8 進数値 N の文字

'\o{40}' は 8 進数 40 で定義される空白文字と一致します。

\xN または \x{N}

16 進数値 N の文字

'\x2C' は、16 進数 2C で定義される、コンマの文字に一致します。

文字表現

演算子

説明

\a

アラーム (ビープ)

\b

バックスペース

\f

フォーム フィード

\n

改行

\r

キャリッジ リターン

\t

水平タブ

\v

垂直タブ

\char

正規表現で特別な意味をもつ文字を、リテラルとして一致させる文字 (たとえば、\\ を使用すると 1 文字のバックスラッシュに一致させます)

量指定子

量指定子は、一致するテキスト内でパターンが発生しなければならない回数を指定します。

量指定子

表現の出現回数

expr*

0 回以上の繰り返し。

'\w*' は任意の長さの単語と一致します。

expr?

0 回または 1 回。

'\w*(\.m)?' はオプションで拡張子 .m で終了する単語と一致します。

expr+

1 回以上の繰り返し。

'<img src="\w+\.gif">' はファイル名に 1 文字以上の文字が含まれている場合、<img> HTML タグと一致します。

expr{m,n}

m 回以上 n 回以下の繰り返し。

{0,1}? と等価です。

'\S{4,8}' は 4 ~ 8 文字の空白文字以外の文字と一致します。

expr{m,}

m 回以上の繰り返し。

{0,} および {1,} は、* および + とそれぞれ等価です。

'<a href="\w{1,}\.html">' はファイル名に 1 文字以上の文字が含まれている場合、<a> HTML タグと一致します。

expr{n}

正確に n 回の繰り返し。

{n,n} と等価です。

'\d{4}' は 4 桁の数と一致します。

量指定子は次の表に示すように、3 つのモードで表示できます。q は前の表の任意の量指定子を表します。

モード

説明

exprq

最長一致表現。できるだけ多くの文字と一致します。

たとえば、テキスト '<tr><td><p>text</p></td>' の場合、式 '</?t.*>'<tr から /td> までのすべての文字と一致します。

'<tr><td><p>text</p></td>'

exprq?

最短一致表現。できるだけ少ない文字と一致します。

たとえば、テキスト '<tr><td><p>text</p></td>' の場合、式 '</?t.*?>' は最初に閉じ山かっこ (>) が出現した時点で、各一致が終了します。

'<tr>' '<td>' '</td>'

exprq+

独占的表現。できる限り多く一致しますが、テキスト部分の再スキャンは実行しません。

たとえば、テキスト '<tr><td><p>text</p></td>' の場合、式 '</?t.*+>' は一致を返しません。これは .* の使用により閉じ山かっこがキャプチャされ、再スキャンされないためです。

グループ化演算子

グループ化演算子を使用すると、トークンをキャプチャしたり、1 つの演算子を複数の要素に適用したり、特定のグループ内のバックトラッキングを無効にすることができます。

グループ化演算子

説明

(expr)

式の要素をグループ化し、トークンをキャプチャします。

'Joh?n\s(\w*)' は、名が John または Jon である人の姓が含まれているトークンをキャプチャします。

(?:expr)

グループ化はしますが、トークンはキャプチャしません。

'(?:[aeiou][^aeiou]){2}''anon' のように、1 つの母音の後に 1 つの子音が続く、2 つの連続パターンと一致します。

グループ化を使用しない場合、'[aeiou][^aeiou]{2}' は 1 つの母音の後に 2 つの子音が続くパターンと一致します。

(?>expr)

アトミックにグループ化します。一致を検索するためにグループ内のバックトラッキングを実行せず、トークンをキャプチャしません。

'A(?>.*)Z''AtoZ' と一致しませんが、'A(?:.*)Z' は一致します。アトミック グループを使用すると、.* を使用することで Z がキャプチャされ、再スキャンは実行されません。

(expr1|expr2)

expr1 または式 expr2 に一致します。

expr1 と一致する場合、expr2 は無視されます。

左小かっこの後に ?: または ?> を入れると、トークンを抑制したりアトミックにグループ化したりできます。

'(let|tel)\w+' は、let または tel を含むがそれらで終わらない単語と一致します。

アンカー

式内のアンカーは、文字ベクトルまたは単語の最初または最後と一致します。

アンカー

一致対象

^expr

入力テキストの最初。

'^M\w*' はテキストの最初が M で始まる単語と一致します。

expr$

入力テキストの最後。

'\w*m$' はテキストの最後が m で終わる単語と一致します。

\<expr

単語の最初。

'\<n\w*'n で始まる任意の単語と一致します。

expr\>

単語の最後。

'\w*e\>'e で終わる任意の単語に一致します。

前後参照アサーション

前後参照アサーションは、目的の一致の直前または直後のパターン (一致の一部ではない) を検索します。

ポインターは現在の位置のままで、test 式に対応する文字はキャプチャも破棄もされません。このため、前方参照アサーションは、オーバーラップしている文字グループと一致することがあります。

前後参照アサーション

説明

expr(?=test)

test と一致する文字を前方参照します。

'\w*(?=ing)' は、入力テキスト 'Flying, not falling.''Fly''fall' など、後ろに ing が続く語句と一致します。

expr(?!test)

test と一致しない文字を前方参照します。

'i(?!ng)' は、後ろに ng が続かない文字 i のインスタンスと一致します。

(?<=test)expr

test と一致する文字を後方参照します。

'(?<=re)\w*' は、入力テキスト 'renew, reuse, recycle''new''use''cycle' など、're' の後に続く語句と一致します。

(?<!test)expr

test と一致しない文字を後方参照します。

'(?<!\d)(\d)(?!\d)' は 1 桁の数字 (前後に他の桁が続かない数字) と一致します。

式の "前に" 前方アサーションを指定する場合、演算は論理 AND と等価になります。

演算

説明

(?=test)expr

testexpr の両方に一致します。

'(?=[a-z])[^aeiou]' は子音と一致します。

(?!test)expr

expr には一致し、test には一致しません。

'(?![aeiou])[a-z]' は子音と一致します。

詳細は、正規表現における先読みアサーションを参照してください。

論理演算子と条件付き演算子

論理演算子と条件演算子を使用すると、特定の条件の状態をテストし、その結果を使用して次に一致するパターン (ある場合) を決定できます。これらの演算子は、論理 OR および if または if/else 条件をサポートします(AND 条件については、前後参照アサーションを参照してください)。

条件には、トークン前後参照アサーションまたは (?@cmd) 形式の動的表現を使用できます。動的表現は、論理値または数値を返さなければなりません。

条件演算子

説明

expr1|expr2

expr1 または式 expr2 に一致します。

expr1 と一致する場合、expr2 は無視されます。

'(let|tel)\w+'let または tel で始まる単語と一致します。

(?(cond)expr)

条件 condtrue の場合、expr に一致します。

Windows® システムで実行する場合、'(?(?@ispc)[A-Z]:\\)'C:\ などのドライブ名と一致します。

(?(cond)expr1|expr2)

条件 condtrue の場合、expr1 に一致します。それ以外の場合は expr2 に一致します。

'Mr(s?)\..*?(?(1)her|his) \w*' は、テキストが Mrs で始まる場合は her を含むテキストに一致し、テキストが Mr で始まる場合は his を含むテキストに一致します。

トークン演算子

トークンは正規表現の一部をかっこで囲んで定義した、一致テキストの一部です。テキスト内のシーケンスによってトークンを参照することも (順序トークン)、コードの保守を簡単にしたり、出力を読み取りやすくしたりするために、トークンに名前を割り当てることもできます。

順序トークン演算子

説明

(expr)

かっこで囲まれた式と一致する文字をトークンでキャプチャします。

'Joh?n\s(\w*)' は、名が John または Jon である人の姓が含まれているトークンをキャプチャします。

\N

N 番目のトークンと一致します。

'<(\w+).*>.*</\1>' はテキスト '<title>Some text</title>''title' など、HTML タグのトークンをキャプチャします。

(?(N)expr1|expr2)

N 番目のトークンが見つかった場合は expr1 に一致します。それ以外の場合は expr2 に一致します。

'Mr(s?)\..*?(?(1)her|his) \w*' は、テキストが Mrs で始まる場合は her を含むテキストに一致し、テキストが Mr で始まる場合は his を含むテキストに一致します。

名前付きトークン演算子

説明

(?<name>expr)

かっこで囲まれた式と一致する文字を名前付きトークンでキャプチャします。

'(?<month>\d+)-(?<day>\d+)-(?<yr>\d+)' は、mm-dd-yy の形式の入力日付に含まれる月、日および年の名前付きトークンを作成します。

\k<name>

name で参照されるトークンに一致します。

'<(?<tag>\w+).*>.*</\k<tag>>' はテキスト '<title>Some text</title>''title' など、HTML タグのトークンをキャプチャします。

(?(name)expr1|expr2)

名前付きトークンが見つかった場合は expr1 に一致します。それ以外の場合は expr2 に一致します。

'Mr(?<sex>s?)\..*?(?(sex)her|his) \w*' は、テキストが Mrs で始まる場合は her を含むテキストに一致し、テキストが Mr で始まる場合は his を含むテキストに一致します。

メモ

式に入れ子にされたかっこがある場合、MATLAB は一番外側のかっこのペアに対応するトークンをキャプチャします。たとえば '(and(y|rew))' という検索パターンの場合、MATLAB は 'andrew' に対するトークンを作成しますが、'y''rew' に対するトークンは作成しません。

詳細は、正規表現におけるトークンを参照してください。

動的表現

動的表現を使用すると、MATLAB コマンドまたは正規表現を実行して一致するテキストを特定できます。

動的表現を囲む小かっこでは、キャプチャするグループを "作成しません"。

演算子

説明

(??expr)

expr を解析して、一致表現内に結果の語句を含めます。

解析時、expr は完全かつ有効な正規表現に対応しなければなりません。バックスラッシュのエスケープ文字 (\) を使用する動的表現では、バックスラッシュを 2 つ使用しなければなりません。1 つは expr の初期解析に使用し、もう 1 つは完全な一致に使用します。

'^(\d+)((??\\w{$1}))' は一致の先頭の 1 桁を読み取ることによって、一致する文字数を決定します。動的表現は、結果の一致がトークンにキャプチャされるように、2 番目のかっこのセットによって囲まれています。たとえば、'5XXXXX' に一致すると、'5''XXXXX' のトークンがキャプチャされます。

(??@cmd)

cmd で表される MATLAB コマンドを実行し、返された出力を一致表現に含めます。

'(.{2,}).?(??@fliplr($1))''abba' など 4 文字以上の回文を検索します。

(?@cmd)

cmd で表される MATLAB コマンドを実行しますが、返された出力をすべて破棄します(正規表現の診断に有効)。

'\w*?(\w)(?@disp($1))\1\w*' は 2 つ連続する文字 (pp など) を含む単語に一致し、中間結果を表示します。

動的表現内では、次の演算子を使って置換語句を定義します。

置換演算子

説明

$& または $0

入力テキストの現在の一致部分

$`

入力テキストの現在の一致の前にある部分

$'

入力テキストの現在の一致の後にある部分 ($'' を使用して $' を表現)

$N

N 番目のトークン

$<name>

名前付きトークン

${cmd}

MATLAB で cmd コマンドを実行したときに返される出力

詳細は、動的正規表現を参照してください。

コメント

comment 演算子では、コードを管理しやすくするために、コメントを挿入できます。コメントのテキストは、入力テキストで一致を検索する際には、MATLAB によって無視されます。

文字

説明

(?#comment)

正規表現にコメントを挿入します。コメントのテキストは、入力の検索時に無視されます。

'(?# Initial digit)\<\d\w+' にはコメントが含まれ、数字で始まる単語に一致します。

検索フラグ

検索フラグは、一致する式の動作を変更します。

フラグ

説明

(?-i)

大文字と小文字を区別します。regexpregexprep の既定です。

(?i)

大文字と小文字を区別しません。regexpi の既定です。

(?s)

パターン内のドット (.) を任意の文字と一致させます (既定)。

(?-s)

パターン内のドットを改行文字以外の任意の文字と一致させます。

(?-m)

テキストの始めと終わりで ^ メタ文字と $ メタ文字を一致させます (既定)。

(?m)

行の始めと終わりで ^$ メタ文字を一致させます。

(?-x)

検索時に空白文字とコメントを含めます (既定)。

(?x)

検索時に空白文字とコメントを無視します。空白文字と # 文字に一致させるには、'\ ''\#' を使用します。

フラグによって修正される式は、かっこの後に

(?i)\w*

のように表示されるか、かっこの中に表示でき、次のようにコロン (:) を使ってフラグから切り離すことができます。

(?i:\w*)

後者の構文を使用すると、大きな式の部分の動作を変更できます。

参考

| | | |

関連するトピック