正規表現 – 雛形

一般

文字列の先頭と末尾の位置指定には^$ではなく\A\zと用いる。

参考:【PHP】マルチバイト(全角スペース等)対応のtrim処理

  • 半角英数記号
  • n文字以上m文字以下
    • \A(文字){n,m}\z
  • patternを含む
    • (?=.*pattern).*
  • patternを含まない
    • (?!.*pattern).*
  • pattern1を含みpattern2を含まない
    • (?=.*pattern)(?!.*pattern).*

雛形

英数字

  • 英文字のみ
    • [a-zA-Z]
  • 英数字
    • [0-9a-zA-Z]
  • \wはアンダースコアを含むので注意
    • [0-9a-zA-Z_]

正の整数

  • /\A[1-9][0-9]*\z/
    • 01や+1は通らない
  • /\A\+?[0-9]*[1-9][0-9]*\z/
    • +001を通す
  • /\A\+?0*[1-9]+(,?[0-9]+)*\z/
    • 先頭に+を許可、その後0の連続を許可、桁内任意位置のカンマを許可

スペース

  • 先頭/末尾の連続するスペース(半角・全角とも)。エスケープ解釈のためダブルクォート
    • "/\A[\x20\xE3\x80\x80]+|[\x20\xE3\x80\x80]+\z/u"

メールアドレス

  • ローカル部は英数字、_、+、-でドットは間に1つずつ、ドメインは英数字、-でドットは間に1つずつ
    • \A([\w+-]+.?[\w+-]+)+@([\w-]+.?[\w-]+)+\z

コメント

  • /*…*/→/\*[\s\S]*?\*/
    • 複数行にわたる場合も可

Python3 – 正規表現 – シンタックス

文字にマッチするもの

一覧

文字 それぞれの文字にマッチする。Python3ではUnicode文字も対象。
. '\n'以外の任意の一文字にマッチする。re.S/re.DOTALLフラグが設定されると’\n’にもマッチする。
[...] 文字クラス。[]内に含まれる文字のいずれか一文字マッチする。'-'で範囲指定も可能。たとえば[abc]abcにマッチ。[a-z]は全ての小文字のアルファベット文字にマッチ。[abcx-z]abcxyzにマッチ。Unicode文字にも対応していて[0-9]は全角の数字にマッチ。先頭に'^'記号があると、その文字クラス以外の文字列がマッチする。たとえば[^abc]abc以外にマッチする。
\d 数字[0-9]にマッチ。Unicode文字の数字も対象となり、全角の数字[0-9]なども対象となる。re.A/re.ASCIIフラグが設定されると[0-9]にのみマッチする。バイト列に対しては[0-9]と等価。
\D 数字以外の文字にマッチ。Unicode文字の数字も除外対象となる。
\w 任意のUnicode単語文字にマッチ。あらゆる単語の一部になりうる文字で、文字・数字・アンダースコアが含まれる。re.ASCIIフラグが設定された場合[a-zA-Z0-9_]にマッチ。バイト列に対しては[a-zA-Z0-9_]と等価。
\W Unicode単語文字以外の文字にマッチ。
\s 任意の空白文字とマッチ。[ \t\n\r\f\v]など。
\S 空白以外の文字にマッチ。

Pythonの標準エスケープも正規表現で認識される。

\a\b\f\n\r\t\u\U\v、\x\\

ただし\bは単語境界を表し、文字クラス内でのみバックスペース文字を表す。

文字クラス

文字クラスはUnicode文字にも対応。

文字クラス内では特殊文字は意味を失い、1つの文字として扱われる。たとえば[(*+)]'(''*''+'')'のいずれかとマッチする。

'^'と、']'は例外で、'^'は先頭の場合のみ否定の意味でそれ以外の位置では文字'^'を表し、']'は末尾では無視されそれ以外の位置では文字']'を表す。

位置にマッチするもの

一覧

^ 文字列の先頭にマッチする。たとえば'^A'は先頭の文字が'A'であることを示す。デフォルトでは文字列全体の先頭だけにマッチするが、re.MULTILINEが指定されていれば、各改行の前にもマッチする。
$ 文字列の末尾にマッチする。たとえば’Z$'は末尾の文字が'Z'であることを示す。デフォルトでは文字列全体の末尾だけにマッチするが、re.MULTILINEが指定されていれば、各改行の後にもマッチする。
\b 単語境界にマッチする。単語境界は[^a-zA-Z0-9]

MULTILINE

re.MULTILINEフラグ指定の有無による動作の違いを確認する。

\b – 文字列境界

文字列境界が[^a-zA-Z0-9]であることが、以下の例で分かる。

繰り返し

 *  直前の文字の0回以上でできるだけ多くの繰り返し。'ab*'abbcに対してaabではなくabbとしてマッチする。
 +  直前の文字の1回以上でできるだけ多くの繰り返し。'ab+'abbbcに対してababbではなくabbbとしてマッチする。'ab?'abb...に対してabとしてマッチする。
 ?  直前の文字が0個か1個でできるだけ多くの場合にマッチ。
{m} 直前の文字のm回の繰り返し。
{m,n} 直前の文字のm回以上n回以下でできるだけ多くの繰り返し。
 {m,}  直前の文字のm回以上でできるだけ多くの繰り返し。
 {,n}  直前の文字のn回以下でできるだけ多くの繰り返し。

実行例

'a*'は長さ0の文字列にもマッチする。マッチした文字列の直後の空文字列にマッチすることが、以下の例でもわかる。

'aa?'aaaにマッチするが、最後のaaaに対しては、先頭のaaにマッチした後、残ったaにマッチしている。

'a{2}'は先頭からaaにマッチしていき、最後のaaaaには2回マッチしている。

'a{,3}'は各マッチの後の長さ0の文字列にもマッチしていて、最後のaaaaに対しては先頭のaaaにマッチした後、残ったaにマッチしている。

選択演算子(|)

'|'で区切られた要素のどれかとマッチすればよいことを表す。

注意点としては、'|'で区切られた要素の左から右へマッチング評価され、ある要素がマッチしたと評価されると、その部分列に対してそれ以降の要素の評価は行われない。

グループ(…)

()で囲んだ要素はグループ化されて、1つの文字と同じ様に扱われる。たとえば次の例では、'Aa'というパターンを1つのグループとして、それが繰り返される回数でマッチングさせている。

後方参照

()囲った部分には、先頭から順番に番号nがふられて、そのあとで'\n'のようにマッチした内容を再利用できる。

 

Python3 – 正規表現 – 選択演算子’|’とfindall/finditerの注意点

findall()finditer()のパターン文字列で選択演算子'|'を用いるとき、選択文字列の順序によって結果が変わってくる点に注意が必要。

たとえばreモジュール関数の場合、以下の例のようになる。

'aa|aaa'とした場合以下の順番でマッチしていく。

  • "a,|aa|,|aa|a,aaaa,aaaaa"
  • "a,|aa|,|aa|a,|aa|aa,aaaaa"
  • "a,|aa|,|aa|a,|aa|aa|,aaaaa"
  • "a,|aa|,|aa|a,|aa|aa|,|aa|aaa"
  • "a,|aa|,|aa|a,|aa|aa|,|aa|aa|a"

'aaa|aa'とした場合は以下の順番でマッチしていく

  • "a,|aa|,aaa,aaaa,aaaaa"
  • "a,|aa|,|aaa|,aaaa,aaaaa"
  • "a,|aa|,|aaa|,|aaa|a,aaaaa"
  • "a,|aa|,|aaa|,|aaa|a,aaaaa"
  • "a,|aa|,|aaa|,|aaa|a,|aaa|aa"
  • "a,|aa|,|aaa|,|aaa|a,|aaa|aa|"

つまり、各マッチングの段階で選択演算子'|'の左側からマッチする部分をまず探し、該当しなければ演算子の右へと判定パターンを変えていく。

このため、演算子の左のパターンが右のパターンより短いと、先にそちらがマッチングされるので右の長いパターンがマッチしなくなることがある。

この動作は、正規表現オブジェクトのメソッドについても同じ。

 

 

Python3 – 正規表現 – エスケープとraw文字列

エスケープの問題

正規表現ではいくつかの文字がパターンとしての特別の意味を持つが、その文字そのものをマッチングの対象としたいときにはバックスラッシュ(\)でエスケープする。

さらに検索対象の文字列にバックスラッシュが含まれている場合には、バックスラッシュ自身をエスケープしなければならない(\\)。このようなケースは、ファイルパスの区切りにバックスラッシュが使われている場合やLATexの\begin~\endなど多くある。

下の例は”\bigin”という文字列を検索する場合。

  • 検索される側の文字列のバックスラッシュをエスケープしなければならない(3行目)
    • その文字列をprintしてみると意図した内容になっている(4行目と9行目)
  • 次にパターン文字の方で、”\begin”とそのまま試してみるとヒットしない(5行目と10行目)
    • これは最初の”\b”がPythonのエスケープシーケンス(バックスペース)として解釈されたため
  • そこでバックスラッシュをエスケープしてもヒットしない(6行目と11行目)
    • Pythonでは文字としてのバックスラッシュとして解釈されるが、今度は正規表現として解釈したとき単独の特殊文字としての’\’となるため
  • 2つのバックスラッシュそれぞれをエスケープするようにしてやっとヒットさせることができる(7行目と11行目)

raw文字列

Pythonでは、バックスラッシュを単なる文字として解釈するためのraw文字列が組み込まれていて、文字列リテラルの前に’r’か’R’を付けるだけでよい。”””で囲まれた複数行文字列でも同じ。

また、Python3で文字列変数の文字列をraw文字列に変換するには、repr()関数を使う。ただしその結果はシングルクォートで囲まれているため、それを取り除かなくてはいけない。

また複数行文字列の場合は、リテラルでのr指定と変数へのrepr()適用で結果が異なってくる。

 

Python3 – 正規表現 – MatchObject

概要

search()などのreモジュール関数正規表現オブジェクトメソッドが実行の結果マッチした場合に、MatchObjectオブジェクトが返される。以下、MatchObjectのオブジェクトをmatchオブジェクトと表現する。matchオブジェクトは常にブール値Trueを持ち、matchオブジェクトそのものを判定式に使ってマッチしたかどうかの判定ができる。

matchオブジェクトの文字列表現には、(最初に)ヒットした場所の範囲と、マッチした内容が含まれている。

正規表現・文字列情報

re

match.re

matchを生成した正規表現オブジェクト。

string

match.string

matchを生成したsearch()match()へ渡された文字列。

グループ指定しない場合のマッチング結果

group()、start()、end()、span()

match.group()match.start()match.end()match.span()

group()はマッチした部分文字列、start()とend()はマッチした部分文字列の開始位置と終了位置、span()は(開始位置, 終了位置)のタプル。

グループ指定した場合のマッチング結果

group()

match.group()match.group([group1, ...])

引数がない場合は、マッチしたもの全てが返される。引数がある場合はグループを指定(数字のほかグループ名でも可)。

groups()

match.groups()

マッチしたグループを要素とするタプルとする。

lastindex

match.lastindex

複数グループの最終インデックス。

 

 

Python3 – 正規表現 – モジュール定数

ここでは正規表現の操作に使われるモジュール定数を整理する。

re.A/re. ASCII
\b\B\d\D\s\S\w\Wにおいて、ASCII文字のみでマッチングを行う。Unicodeパターンでのみ意味があり、バイト列パターンでは無視される。
re.I/re.IGNORECASE
英大文字・小文字を区別せずにマッチングを行う。{A-Z]のような表現で小文字ともマッチする。現在のロケールに影響を受けず、Unicode文字に対しても動作する。
re.L/re.LOCALE
\b\B\s\S\w\Wにおいて、現在のロケールに従ったマッチングを行う。バイト列でのみ意味を持つ。非推奨。
re.M/re.MULTILINE
デフォルトでは'^'は文字列全体の先頭に、'$'は文字列全体の末尾にのみマッチするが、このフラグにより、'^'は文字列の先頭と各行の先頭(各改行の直後)、'$'は文字列の末尾と各行の末尾(各改行のの直前)とマッチする。
re.S/re.DOTALL
デフォルトでは'.'は改行にマッチしないが、このフラグにより'.'を改行を含む任意の文字とマッチさせる。
re.X/re.VERBOSE
このフラグにより、パターン文字列内に改行・インデントを入れたりコメントを入れるなど、より読みやすい正規表現を書くことができる。コメントには'#'を使う。

Python3 – 正規表現 – 正規表現オブジェクトメソッド

概要

reモジュールではre.RegexObjectクラスが定義されている。パターン文字列をコンパイルするとRegexObjectのオブジェクトが生成され、そのパターンはそのプロパティとして保持される。このクラスの各メソッドで、パターンを任意のテキストに適用する。

reモジュール関数を使う場合は実行のたびにパターン文字列とフラグを指定し、その都度コンパイルされる。一方、正規表現オブジェクトのメソッドを使う場合は、一度パターンをコンパイルしておけば、その後の操作でコンパイルのオーバーヘッドが生じない。フラグはコンパイル時に指定する。

パターンの検索

search()

regex.search(string,[ pos[, endpos]])

re.search()関数と同じ機能で、stringの任意の位置で、最初にregexにマッチした時にMatchObjectのオブジェクトを返す。マッチしなければNoneを返す。

posは検索開始位置で先頭が0。デフォルト値は0で先頭から検索する。

endposは検索範囲の終了位置で、endpos-1文字目までが検索範囲となる。デフォルトでは文字列の最後まで検索する。

match()

regex.match(string[, pos[, endpos]])

re.match()関数と同じ機能で、regexstringの先頭でマッチするときだけMatchObjectオブジェクトを返す。posendposregex.search()と同じ意味。

fullmatch()

regex.fullmatch(string[, pos[, endpos]])

re.fullmatch()関数と同じ機能で、regexstring全体にマッチするときだけMatchObjectオブジェクトを返す。posendposregex.search()と同じ意味。

findall()

regex.findall(string[, pos[, endpos]])

re.findall()関数と同じ機能でregexにマッチする部分列のリストを返す。posendposregex.search()と同じ意味。

finditer()

regex.finditer(string[, pos[, endpos]])

re.finditer()関数と同じ機能で、regexにマッチする部分列のイテレータを返す。posendpossearch()と同じ意味。

分割

split()

regex.split(string, maxsplit=0)

re.split()関数と同じ機能で、regexにマッチする部分列でstringを切り分ける。posendpossearch()と同じ意味。

置換

sub()

regex.sub(repl, string, count=0)

re.sub()関数と同じ機能でstring中のregexにマッチする部分をreplで置き換える。replには文字列を返す関数も指定可能。posendpossearch()と同じ意味。

subn()

regex.subn(repl, string, count=0)

re.subn()関数と同じ機能で、置換後にタプルで(置換後の文字列, 置換数)を返す。posendpossearch()と同じ意味。

 

Python3 – 正規表現 – モジュール関数

概要

reモジュールの関数は、パターンと文字列を直接指定してマッチングなどの操作を行う。

引数の中のflagsについては、reモジュールで定義された定数を指定する。複数のflagsを指定する場合は、ビットごとのOR('|'演算子)を使って組み合わせる。

パターンは実行に先立ってコンパイルされるので、同じパターンを複数回用いる場合には、re.compile()関数でパターンをコンパイルし、コンパイルされたRegexObjectオブジェクトのメソッドを用いる方がよい。

正規表現のコンパイル

compile()

re.compile(pattern, flags=0)

正規表現パターンを正規表現オブジェクトにコンパイルする。正規表現オブジェクトのメソッド群で、以下のモジュール関数と同等の操作を行うことができる。

以下のモジュール関数を使う場合はflagsを関数ごとに指定するが、正規表現オブジェクトを使う場合は、compile()関数の引数でflagsを指定する。

パターンの検索

re.search(pattern, string, flags=0)

stringの任意の位置で、最初にpatternにマッチした時にMatchObjectのオブジェクトを返す。マッチしなければNoneを返す。

match()

re.match(pattern, string, flags=0)

stringの先頭でpatternにマッチすればMatchObjectのオブジェクトを返す。マッチしなければNoneを返す。stringの途中ではマッチしない。

fullmatch()

re.fullmatch(pattern, string, flags=0)

patternstring全体にマッチしたときだけMatcObjectのオブジェクトを返し、それ以外はNoneを返す。

findall()

re.findall(pattern, string, flags=0)

string中でpatternにマッチする全ての部分文字列を要素とするリストを返す。マッチする部分がなければ空のリスト([])を返す。先頭からマッチした部分を取り除きながらサーチしていく。

finditer()

re.finditer(pattern, string, flags=0)

string中でpatternにマッチした結果のMatchObjectオブジェクトのイテレータを返す。マッチする部分がなければ空のイテレータを返す。先頭からマッチした部分を取り除きながらサーチしていく。

分割

split()

re.split(pattern, string, maxsplit=0, flags=0)

stringをすべてのpatternにマッチする部分で分割し、それらを要素とするリストを返す。patternにマッチする部分は除かれる。マッチする部分がなければ、stringを1つの要素とするリストが返される。

maxsplitに1以上の数nを指定すると、先頭から最大n個の分割が発生し、残りはリストの最後の要素となる。

patternが先頭の部分に一致する場合は、リストの最初は空文字列から始まり、最後の部分に一致する場合はリストの最終要素が空文字列になる。

空文字列('')では分割されない。patternとして空文字1文字を指定するとエラー。

置換

sub()

re.sub(pattern, repl, string, count=0, flags=0)

string中でpatternにマッチする部分文字列をreplの文字列で置換する。countで正の整数値を指定すると、先頭から最大その回数だけ置換を行う。

空文字列とのマッチは、前のマッチの直後以外に置換される。

replには文字列を返す関数を指定できる。

subn()

re.subn(pattern, repl, string, count=0, fkags=0)

sub()と同じ操作を行うが、タプルで(置換後の文字列, 置換数)を返す。

 

Python3 – 正規表現

Pythonでの正規表現の扱い

Pythonでは、パターン・マッチングを以下のいずれかの方法で行い、その結果をMatchObjectオブジェクトとして返す。

  • パターンと文字列を指定して、reモジュールで定義された関数を実行する
  • パターン文字列を正規表現オブジェクトとしてコンパイルしておき、そのメソッドで文字列を指定して実行する

reモジュール関数を使う方法

モジュール関数で実行する例は次の通り。実行結果はMatchObjectのオブジェクトとして返されるが、その文字列表現のspanのところに4文字目~8-1文字目でヒットしたことが記録されている。

パターン文字列を正規表現オブジェクトにコンパイルする方法

正規表現オブジェクトにコンパイルして検索する方法は次の通り。検索結果は先と同じMatchObjectオブジェクト。