Python 正規表現チュートリアル

胡金庫 2023年12月11日
  1. Python 正規表現 re.match() 関数
  2. Python 正規表現の re.search() 関数
  3. re.complie で正規表現をコンパイルする
  4. Python 正規表現の re モジュールのフラグ
  5. 許可された文字の確認
  6. 検索と置換
  7. findall() 関数
  8. finditer() 関数
  9. split() 関数
  10. re の基本パターン
  11. 繰り返しの場合
  12. 貪欲でない繰り返し
  13. re の特殊文字とシーケンス
  14. escape 関数
  15. group() 関数
Python 正規表現チュートリアル

このチュートリアルでは、Python の re モジュールで定義された正規表現と正規表現操作を学習します。re は、正規表現のマッチング操作をサポートする Python の標準ライブラリです。

Python の正規表現は、正式な構文を使用して文字列を別のパターンに一致させるために使用される文字またはシーケンスのセットです。正規表現は、Python に埋め込まれた小さなプログラミング言語と考えることができます。

正規表現を使用していくつかのルールを定義し、これらのルールを使用して、パターンと一致させる特定の文字列から可能な文字列を作成します。Python の正規表現は、一連の命令として解釈されます。

Python 正規表現 re.match() 関数

一致機能を使用して、RE パターンを指定の文字列と一致させることができます。一致関数にはフラグが含まれています。フラグは正規表現の動作を定義し、このチュートリアルの後半で表示されるさまざまな値を含めることができます。

Python の match 関数の構文は次のとおりです。

re.match(pattern, string, flags)

3つの引数があります。

  1. pattern は、一致する正規表現パターンです
  2. string は、正規表現と一致する特定の文字列です
  3. flags は正規表現の動作を変更するために使用され、オプションです。

マッチングが正常に実行されると、match オブジェクトが返され、そうでない場合は None が返されます。match オブジェクトには、group(num)group() 関数であるさらに 2つの主要なメソッドがあります。これらの関数を使用する主な目的は、一致または特定のサブシーケンスとすべてのサブシーケンスをそれぞれ返すことです。

re.match 関数を使用する

次の例は、match 関数の使用方法を示しています。

import re

strTest = "Hello Python Programming"
mobj = re.match(r"hello", strTest, re.I)
print(mobj.group())

このコードでは、まず re モジュールがインポートされます。次に、文字列 strTest を RE パターンと比較し、一致関数から返された値が mobj に割り当てられます。マッチ関数は re を使用して呼び出され、括弧内の最初の引数は照合されるパターンであり、パターンが照合される元の文字列とフラグ値が渡されます。ここで、re.IIGNORECASE を意味するフラグ値であるため、パターンと文字列で大文字と小文字が異なるかどうかは無視されます。

出力は次のとおりです。

Hello

この例では、文字列が生の文字列であることを示す接頭辞 r が使用されます。生の文字列では、エスケープシーケンスを使用するときにダブルスラッシュを記述する必要はありません。たとえば、バックスラッシュが必要な場合は、通常の文字列のように単一の \があり、二重のバックスラッシュはありません。これは、通常の文字列と生の文字列の唯一の違いです。

通常の文字列で re.match 関数を使用する

生の文字列の代わりに通常の文字列が使用される以下の例を考えてください。

import re

str = "\\tHello Python Programming"
mobj = re.match("\\thello", str, re.I)  # no match

str = "\tHello Python Programming"
mobj = re.match("\\thello", str, re.I)  # \thello is matching

Python 正規表現の re.search() 関数

re.search() 関数を使用して、指定された文字列で RE パターンを検索できます。search 関数には、関数に 3つの引数が含まれ、それぞれ stringflags(オプション)が与えられた pattern があります。

Python の検索関数の構文は次のとおりです。

re.search(pattern, string, flags)

次の Python コードは、search() 関数の使用方法を示しています:

import re

str = "Hello Python Programming"
sobj = re.search(r"programming", str, re.I)
print(sobj.group())
Programming

このコードでは、プログラミングという単語の検索が行われています。search 関数は文字列全体を検索します。search と match の違いは、match 関数は文字列の先頭でのみチェックするのに対して、search は文字列全体を検索することです。

re.search を使用して最初に検索する

文字列の先頭で検索したい場合は、^を使用できます。次の例を考えてみましょう。

import re

str = "Hello Python Programming"
sobj = re.search(r"^programming", str, re.I)
print(sobj.group())  # no match is found

sobj = re.search(r"^hello", str, re.I)
print(sobj.group())  # matching: Hello

ここで、^は文字列の先頭でのみ検索を行います。

re.search を使用して最後に検索する

与えられた文字列の最後で検索することもできます。パターンの最後で $ を使用して実行できます。以下のコードを検討してください。

import re

str = "Hello Python Programming"
sobj = re.search(r"programming$", str, re.I)
print(sobj.group())  # matching: Programming

sobj = re.search(r"hello$", str, re.I)
print(sobj.group())  # no match found

re.complie で正規表現をコンパイルする

コンパイル時の Python の正規表現は、パターンに変換されます。これらのパターンは、実際には、検索、マッチング、置換などを含むさまざまなタスクを実行するためのさまざまな機能を含むパターンオブジェクトです。

パターンをコンパイルすると、プログラムで後でそのパターンを使用できます。

プリコンパイルされたパターンを使用する

文字列の最初の数字を意味するパターン r"\d" がコンパイルされる以下のコードを考えてください。次に、このパターンを使用して検索関数を呼び出し、検索関数に文字列を渡します。このパターンは、検索機能に提供された文字列で検索されます。同様に、次のように、このプリコンパイルされたパターンと一致関数を使用できます。

import re

compPat = re.compile(r"(\d)")
sobj = compPat.search("Lalalala 123")
print(mobj.group())

mobj = compPat.match("234Lalalala 123456789")
print(mobj.group())
1
2

Python 正規表現の re モジュールのフラグ

Flags を使用して、正規表現の動作を変更できます。関数では、フラグはオプションです。フラグは、キーワード flags を使用してフラグ値を割り当てるか、フラグの値を直接書き込むことにより、2つの異なる方法で使用できます。RE リテラルには flag の値を複数持つことができます。これは、ビット単位の OR 演算子|を使用して実行できます。

一般的に使用されるフラグの一部が正規表現リテラルで説明されている次の表を検討してください。

フラグ値 説明
re.I この修飾子は、マッチング中に文字列とパターンの大文字と小文字を無視します。
re.L この修飾子は、現在のロケールに関して単語を解釈するために使用されます。
re.M この修飾子は、文字列の終わりではなく、行の終わりに一致するように $ を作成するために使用されます。同様に、^は文字列の先頭ではなく、行の先頭で一致します。
re.S この修飾子は、任意の文字に一致するドットを作成するために使用されます。これには改行も含まれます。
re.U この修飾子は、文字を Unicode 文字セットとして解釈するために使用されます。
re.X 空白を無視するために使用されます。コメントのマーカーとして # を作成します。

複数のフラグ値を使用する

複数のフラグ値を使用して RE の動作を変更する方法がわかる以下の Python コードを検討してください。ビットごとの OR(|) 演算子により、複数のフラグ値を含めることができます。

import re

s = re.search("L", "Hello")
print(s)  # Output: None, L is there but in small letter and we didn't use flags

s = re.search("L", "Hello", re.I)
print(s)  # Output: 1

s = re.search("L", "^Hello", re.I | re.M)
print(s)  # Output: 1, searching will be made from the start of line and case is ignored

許可された文字の確認

特定の文字列に特定の範囲の文字が含まれているかどうかも確認できます。

関数の定義と使用可能な文字の確認

関数が定義され、プリコンパイルされたパターンを使用して、特定の文字が渡された文字列に含まれているかどうかを確認する次の例を考えてみましょう。

import re


def check(str):
    s = re.compile(r"[^A-Z]")
    str = s.search(str)
    return not bool(str)


print(check("HELLOPYTHON"))  # Output: True
print(check("hellopython"))  # Output: False

この関数では、r'[^ A-Z]' というパターンがコンパイルされ、check という名前のこの関数が呼び出されたときに渡される文字列を検索するために使用されます。この関数は、渡された文字列に文字 A-Z(大文字)が含まれているかどうかを実際にチェックします。同様に、小文字の文字列を渡すと False が返されることがわかります。

検索と置換

re モジュールは、関数の repl 属性を使用して、指定された string 内の pattern のすべての出現を置き換えるために使用される sub 関数である関数を提供します。文字は、カウント数に達するまで置き換えられます。sub 関数は更新された文字列を返します。

以下は、サブ関数の構文です。

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

sub 関数を使用する

sub 関数が文字列全体を与えられた文字列で置き換える以下の例を考えてください:

import re

s = "Playing 4 hours a day"
obj = re.sub(r"^.*$", "Working", s)
print(obj)
Working

ここでは、sub 関数が使用されます。パターン r'^.*$ は、文字列の先頭から開始することを意味し、次に .* は、文字列内のすべての文字列の最後の $ までを意味します。次に、引数 "Working"が文字列 s 全体を置き換えます。

sub 関数を使用して文字列からすべての数字を削除する

sub 関数が与えられた文字列の数字を削除する次の例を考えてみましょう。この目的のために、\d を使用できます:

import re

s = "768 Working 2343 789 five 234 656 hours 324 4646 a 345 day"
obj = re.sub(r"\d", "", s)
print(obj)
Working   five   hours   a  day

同様に、文字列から文字を削除できます。この目的のために、\D を使用できます。

import re

s = "768 Working 2343 789 five 234 656 hours 324 4646 a 345 day"
obj = re.sub(r"\D", "", s)
print(obj)
76823437892346563244646345

findall() 関数

findall 関数は、パターンに一致するすべての文字列のリストを返します。search 関数と findall 関数の違いは、findall がすべての一致を検出するのに対して、search は最初の一致のみを検出することです。この関数は、重複しない一致を検索し、文字列のリストとして返します。

findall 関数の構文は次のとおりです。

findall(pattern, string, flags)

ここで、パターンは、大文字と小文字を無視する re.I など、いくつかのフラグ値を持つ特定の文字列で見つかる RE パターンです。

重複しないすべての一致を検索

次の例では、findall は重複しない一致を検索します。

import re

str = "Working 6 hours a day. Studying 4 hours a day."
mobj = re.findall(r"[0-9]", str)
print(mobj)
["6", "4"]

r'[0-9]' is a pattern finding all the digits in the given string and a list of strings is returned (no matter they are digits) which is stored in mobj.

ファイルを使用した findall

findall を使用してファイルを検索することもできます。ファイルで findall を使用すると、ファイル内の一致するすべての文字列のリストが返されます。ファイルの read() 関数が使用されるため、ファイルのテキスト全体を文字列として返すため、ループを使用してファイルの各行を繰り返す必要はありません。次の例を考えてみましょう。

import re

file = open("asd.txt", "r")
mobj = re.findall(r"arg.", file.read())
print(mobj)
file.close()
["arg,", "arg,", "arg,", "argv", "argv", "argv"]

この例では、ファイルは最初に読み取りモードで開かれます。パターン r'arg.'はファイルの内容と一致し、出力には一致する文字列のリストがあります。

finditer() 関数

finditer 関数は、文字列のインデックスである一致する文字列の位置とともに文字列内の RE パターンを見つけるために使用できます。この関数は、実際に一致する文字列を反復処理し、文字列のインデックスまたは場所を返します。

finditer 関数の構文は次のとおりです。

finditer(pattern, string, flags)

マッチの繰り返し

findallfinditer の唯一の違いは、finditer が一致する文字列とともにインデックスを返すことです。次のコードでは、finditer を使用して、for ループを使用して一致(一致する文字列)を反復処理しながら、一致する文字列の場所を検索します。

import re

str = "Working 6 hours a day. Studying 4 hours a day."
pat = r"[0-9]"
for mobj in re.finditer(pat, str):
    s = mobj.start()
    e = mobj.end()
    g = mobj.group()
    print("{} found at location [{},{}]".format(g, s, e))
6 found at location [8,9]
4 found at location [32,33]

この例では、パターンは str にある 0〜9 の数字です。for ループは、finditer によって返された一致する文字列を反復処理します。ループ内では、関数 startend、および group は、開始インデックス、終了インデックス、および findder によって返された文字列の各反復で見つかった一致をそれぞれ返します。

split() 関数

split 関数は文字列を分割するために使用されます。

以下は、分割関数の構文です。

split(patter, string, maxsplit, flags)

ここで、max は文字列分割の総数です。最大で maxsplit の分割が発生する場合、文字列の残りの部分はリストの最後の要素として返されます。max のデフォルト値は 0 で、無制限の分割を意味します。

文字列を分割する

split 関数は文字列内の各単語を返します

次のコードでは、指定されたパターンと最大分割数に従って文字列が分割されます。

import re

str = "Birds fly high in the sky for ever"
mobj = re.split("\s+", str, 5)
print(mobj)
["Birds", "fly", "high", "in", "the", "sky for ever"]

この例では、パターン文字 \s は空白文字に一致する特殊文字で、[ \t\n\r\f\v] と同等です。したがって、単語を区切ることができます。ここで max の値は 5 で、これは 6 の分割を行い、最後の要素は 5 番目の分割後の文字列の残りです。

re の基本パターン

正規表現は、特定の文字列と比較されるパターンを指定できます。正規表現の基本パターンは次のとおりです。

パターン 説明
^ 文字列の先頭で一致させるために使用されます。
$ このパターンは、文字列の末尾で一致します。
. ドットは、1 文字と一致するために使用されます(改行は含まれません)。
[...] 括弧内の単一の文字と一致させるために使用されます。
[^...] これは単一の文字に一致しますが、括弧内には一致しません。
* 指定された文字列内の先行する re の 0 回以上の出現。
+ 指定された文字列で先行する re が 1 回以上出現します。
? 指定された文字列内の先行する re の 0 または 1 回の出現。
{n} 指定された文字列の n 個の出現に一致します。
{n,} n 回または n 回以上の出現に一致します。
{n,m} このパターンは、ストリング内の少なくとも n 個、最大 m 個の一致に使用されます。
`a b`
(re) このパターンは、正規表現をグループ化するために使用され、一致したテキストを記憶します。
(?imx) RE で i または m または x を一時的に切り替えます。括弧を使用する場合、括弧領域のみが影響を受けます。
(?-imx) RE の i または m または x を一時的にオフにします。括弧を使用する場合、括弧領域のみが影響を受けます。
(?: re) このパターンは、正規表現をグループ化するために使用されますが、一致したテキストを記憶しません。
(?imx: re) 括弧内の RE で i または m または x を一時的に切り替えます。
(?-imx: re) 括弧内の RE の i または m または x を一時的にオフにします。
(?#...) コメントです。
(?=re) パターンを使用して位置を指定するために使用されます。範囲はありません。
(?!re) パターン否定を使用して位置を指定するために使用されます。範囲はありません。
(?>re) このパターンは、独立したパターンと一致するために使用されます。
\w このパターンは、単語の一致に使用されます。
\W このパターンは、非単語の照合に使用されます。
\s 空白と一致します。\s[ \t\n\r\f] と同じです。
\S 空白以外と一致します。
\d に等しい [0-9]。文字列の数字と一致します。
\D 数字以外と一致します。
\A 文字列の先頭に一致します。
\Z 文字列の末尾に一致します。改行がある場合、改行の前に一致します。
\G 最後の一致が終了したポイントに一致します。
\b 括弧の外側にある場合は単語の境界に一致しますが、括弧内にある場合はバックスペースに一致します。
\B 非単語境界に一致します。
\n, \t, etc. \n は改行の照合に使用され、\t はタブの照合などに使用されます。
\1...\9 このパターンは、n 番目の部分式(グループ化された)と一致します。
\10 \ 10 は通常、一致が既に行われている場合、n 番目の部分式(グループ化された)と一致します。一致がまだ行われていない場合、\ 10 は文字コードの 8 進数表現を提供します。

繰り返しの場合

次の表は、説明付きの繰り返しの例をいくつか示しています。

説明
ab? a または ab のいずれかに一致します。
ab* ab *は、ab と a および a の後に b が続くものに一致します。
ab+ ab + は、a だけでなく、a の後に b が続くことを意味します。a の後にゼロ以外の b が続く必要があります。
\d{2} 正確に 2 桁に一致します。
\d{2,} 2 桁以上に一致します。
\d{2,4} 2、3、4 桁と一致します。

貪欲でない繰り返し

正規表現では、繰り返しはデフォルトで貪欲であり、できるだけ多くの繰り返しに一致しようとします。

*+? などの修飾子は、貪欲な修飾子です。.*を使用すると、貪欲な一致が実行され、文字列全体が一致するため、可能な限り多くの文字が一致します。以下のコードを検討してください。

import re

mobj = re.match(r".*", "Birds fly high in sky")
print(mobj.group())
Birds fly high in the sky

したがって、文字列全体が一致していることがわかります。

.+? を追加すると、欲張りでない re が返され、パターン .+? は文字列内のできるだけ少ない文字に一致します。

import re

mobj = re.match(r".*", "Birds fly high in sky")
print(mobj.group())

結果は文字列の最初の文字です

B

re の特殊文字とシーケンス

re の特殊文字は\で始まります。たとえば、文字列の先頭から一致する \A があります。

これらの特殊文字については、上の表で説明しています。

このセクションでは、いくつかの特殊文字の例を示します。

import re

str = "Birds fly high in the sky"
# \A
# OUTPUT: B, here \A will match at beginning only.
mobj = re.match(r"\Ab", str, re.I)

# \d
mobj = re.match(r"\d", "4 birds are flying")  # OUTPUT: 4

# \s
mobj = re.split("\s+", "birds fly high in the sky", 1)  # OUTPUT: ['Birds', 'fly']

escape 関数

escape 関数は、文字列からすべての文字をエスケープするために使用されます。ASCII 文字、数字、および _ はエスケープされません。文字列からメタキャラクターを抽出したい場合は、escape 関数を使用します。

エスケープ関数の構文は次のとおりです。

escape(pattern)

次の例では、文字列 www.python.org がエスケープ関数に渡されます。これには、メタキャラクターである . があり、抽出または照合されます。

print(re.escape("www.python.org"))
www\.python\.org

ここで、. は抽出または一致するメタキャラクターです。エスケープ関数を使用してメタ文字が一致する場合は常に、文字の前に \ が付きます。

特殊文字のエスケープ

角カッコ [ および ] のような文字は一致しません。次の例を考えてみましょう。

import re

mobj = re.search(r"[a]", "[a]b")
print(mobj.group())
a

ここでは、括弧 [] が一致していないことがわかります。

エスケープ関数を使用してそれらを一致させることができます。

import re

mobj = re.search(r"\[a\]", "[a]b")
print(mobj.group())
[a]b

group() 関数

group 関数は、見つかった一致の 1つ以上のサブグループを返すために使用されます。group 関数にはいくつかの引数があります。

グループ関数の構文は次のとおりです。

group(group1, group2, ..., groupN)

グループ関数に単一の引数がある場合、結果は単一の文字列になりますが、複数の引数がある場合、結果はタプル(引数ごとに 1つのアイテムを含む)になります。

引数がない場合、デフォルトでは引数はゼロになり、一致全体が返されます。

引数 groupN がゼロの場合、戻り値は一致する文字列全体になります。

グループ番号または引数を負の値またはパターン内のグループ数よりも大きい値として指定すると、IndexError 例外が発生します。

group(0) と同等の group 関数に引数がない以下のコードを考えてください。

import re

str = "Working 6 hours a day"
mobj = re.match(r"^.*", str)
print(mobj.group())
Working 6 hours a day

ここでは group() が使用され、一致した文字列全体があります。

一致するテキストの一部を選択する

次の例では、group 関数を引数とともに使用して、一致するグループを取得します。

import re

a = re.compile("(p(q)r)s")
b = a.match("pqrs")
print(b.group(0))
print(b.group(1))
print(b.group(2))
pqrs
pqr
q

ここで、group(0) はマッチ全体を返します。group(1)pqr である最初の一致を返し、group(2)q である 2 番目の一致を返します。

名前付きグループ

名前付きグループを使用して、キャプチャグループを作成できます。このグループは、名前で参照できます。以下の例を検討してください。

import re

mobj = re.search(r"Hi (?P<name>\w+)", "Hi Roger")
print(mobj.group("name"))
Roger

非キャプチャグループ

非キャプチャグループは、?: を使用して作成できます。非キャプチャグループは、グループのコンテンツが必要ない場合に使用されます。

import re

mobj = re.match("(?:[pqr])+", "pqr")
print(mobj.groups())
()
著者: 胡金庫
胡金庫 avatar 胡金庫 avatar

DelftStack.comの創設者です。Jinku はロボティクスと自動車産業で8年以上働いています。自動テスト、リモートサーバーからのデータ収集、耐久テストからのレポート作成が必要となったとき、彼はコーディングスキルを磨きました。彼は電気/電子工学のバックグラウンドを持っていますが、組み込みエレクトロニクス、組み込みプログラミング、フロントエンド/バックエンドプログラミングへの関心を広げています。

LinkedIn Facebook