🫠

正規表現をpythonのreで検証

2024/12/15に公開

pythonの標準モジュールreについて

公式のリンクは以下
https://docs.python.org/ja/3.13/library/re.html
公式の内容を要約すると以下である。

  • Unicode 文字列 (str) や 8 ビット文字列 (bytes)を対象に検索できる。
  • Unicodeと8ビット文字列が混在した形では検索できない。
  • バックスラッシュ\の扱いについて、"\"を文字列として検索したければ、r stringを使用すること。
  • 正規表現記法
  • reの所持する関数についての説明

上記のうち下から2つについては、おおまかなものをとりあげて以下に記す。

正規表現記法

正規表現記法 説明 使用例 例で検索できる文字列 例で検索できない文字列
. 任意の1文字 abc.d abccd,abcgd,abchd

abc_dの_に改行以外の任意の1文字が入っているものを検索できる
abcccd,abcc
^ 先頭を指定 ^abcd abcde,abcd,abcdefg

先頭がabcdで始まる文字列を検索できる
fabcd,rtuabcd
$ 末尾であることを指定 abcd$ fabcd,xyzabcd,456abcd,abcd

末尾がabcdで終わるものを検索できる。
(MULTILINEモードでは、改行の前にもマッチ)
abcde,aabcd23
* 直前の文字・正規表現を 0 回以上、できるだけ多く繰り返したものにマッチ abcd* abc,abcd,abcddd

abcdだと直前のdを0回以上繰り返すものなので、abc~という文字列の検索ができる
ab,abgyu
+ 直前の文字・正規表現を 1 回以上繰り返したものにマッチ abcd+ abcd,abcdddd,abcd123

abcd+だと+直前のdを1回以上繰り返すものなので、abc~という文字列の検索ができる
abc,abcfgh,bcdghk
? 直前の正規表現を 0 回か 1 回繰り返したものにマッチ abcd? abc,abcd,abcccc,abcddd

abcd?だとdを0回か1回繰り返したものにマッチなので、abc~と続くものを検索できる
abbbb,aaakl
* 直前の文字・正規表現を 0 回以上、できるだけ多く繰り返したものにマッチ abcd* abc,abcd,abcddd

abcdだと直前のdを0回以上繰り返すものなので、abc~という文字列の検索ができる
ab,abgyu
+ 直前の文字・正規表現を 1 回以上繰り返したものにマッチ abcd+ abcd,abcdddd,abcd123

abcd+だと+直前のdを1回以上繰り返すものなので、abc~という文字列の検索ができる
abc,abcfgh,bcdghk
? 直前の正規表現を 0 回か 1 回繰り返したものにマッチ abcd? abc,abcd,abcccc,abcddd

abcd?だとdを0回か1回繰り返したものにマッチなので、abc~と続くものを検索できる
abbbb, aaakl
{m} 直前の正規表現をちょうど m 回繰り返したものにマッチ ^a{3}bcd aaabcd

aを3回繰り返したあとにbcdが続いたものを判定
aabcd, aaaabcd,
{m,n} 直前の正規表現を m 回から n 回、できるだけ多く繰り返したものにマッチ ^a{3,5}bcd aaabcd,aaaabcd,aaaaabcd

aを3回~5回繰り返したあとにbcdが続いたものを判定
aabcd,aaaaaaaabcd,aaabcc
[] 文字の集合を指定するのに使います [0-9] 0,1,6,9,ar34,6a67

0~9の数字一文字にマッチします。
abc,abcdddd,ABC
[0-9][1-3] 12,52,124,2256,5633

0~9の数字1文字に1~3の数字が続いたものをマッチとします。
155,abc,556,78967,ABC
[a-z] 3456yy,abc,e,er456

a-zの小文字アルファベットの入っている文字列をマッチ
2,ABC456,34556,
[A-Z] 123A,B,345hjzB

A-Zの大文字アルファベットが一つでも入っていればマッチ
234ja,567
[^1-3] 4,45,35,672,z,abc

1~3の文字が含まれていない集合にマッチ
33,2,1
[^1-3][a-c][A-D] 4aD,5bC,7t7bB,AcC,acC

①②③の三つの文字列の配列で、①が1~3の文字列を含まず、②にa-cの小文字を含み、③にA-Dの大文字を含む文字列が①②③の順番であるとマッチ
1aD,4AD,4Ad,56gD,56gd
| A と B を任意の正規表現として、 A|B は A と B のいずれかにマッチする正規表現を作成 a|b a,b,cba,bcc,ccab

この場合、aかbのどちらかがマッチすればいいので、ひとたびaがマッチするとbをそのあとさがそうとはしません。
c,ccd,123

元のサイトにはもっといろいろ載っているので、いろいろ省略しております。

関数について

関数名 説明 コメント
re.compile(pattern, flags=0) 正規表現パターンを 正規表現オブジェクト にコンパイルし、以下に述べる match() 、 search() その他のメソッドを使ってマッチングに使えるようにします 先にコンパイルして置いておいた方があとあと再利用する場合には効率的
re.search(pattern, string, flags=0) string 全体を走査して、正規表現 pattern がマッチを発生する最初の位置を探して、対応する Match を返します。もし文字列内に、そのパターンとマッチする位置がないならば、 None を返します 文中でもマッチしたらMatchになります。
re.match(pattern, string, flags=0) もし string の先頭で 0 個以上の文字が正規表現 pattern とマッチすれば、対応する Match を返します。もし文字列がパターンとマッチしなければ、 None を返します 先頭でマッチしたら、Matchになります。
re.fullmatch(pattern, string, flags=0) string 全体が正規表現 pattern にマッチするなら、対応する Match を返します。文字列がパターンにマッチしないなら None を返します 全部正規表現に完全に一致しないとMatchになりません。
re.split(pattern, string, maxsplit=0, flags=0) string を、出現した pattern で分割します。 pattern 中でキャプチャの丸括弧が使われていれば、パターン中の全てのグループのテキストも結果のリストの一部として返されます。 これは、使ってみてください。文章で書いてあるのを読んでもわかりにくいです。
re.findall(pattern, string, flags=0) 文字列内のパターンの重複しない一致をすべて、文字列またはタプルのリストとして返します これは、使ってみてください。文章で書いてあるのを読んでもわかりにくいです。
re.purge() 正規表現キャッシュをクリアします。 キャッシュのクリア

こちらも少し省略しています。

私は、正規表現は、苦手意識があります。

正規表現例

以下は、私がぶちあたった難問たちです。

  • ^.*\)\.1←これは、何を意味しているでしょうか?
    まず、分解すると.*は、任意の1文字.*0回以上繰り返してあることを表します。
    \)これは、バックスラッシュで)をエスケープしています。
    \.これは、同じくバックスラッシュで.をエスケープしています。
    つまりこれは、任意の文字列が続いたあとに).1となるような文字にマッチするものを抽出します。
  • ^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$←これは、何を意味しているでしょうか?
    ^[a-zA-Z0-9_.+-]+は、小文字、大文字のアルファベットと0~9の数字や_.+-を含んだ文字を先頭にして(先頭の^)、それらを1つ以上繰り返した(最後の+)集合
    @[a-zA-Z0-9-]+@のあとに小文字、大文字のアルファベットと数字-のいずれかの入った集合を1つ以上繰り返す(最後の+)
    \.[a-zA-Z0-9-.]+$.は、.を文字列として扱うためのエスケープなので、.のあとに小文字、大文字アルファベットと数字-.の入った集合が1つ以上繰り返して(の前の+)文末になる(最後の
    つまり、これはEmailアドレスを示唆していますね。

肯定先読み・否定先読み・否定後読み・肯定後読み

これ、すごくわかりにくいですよね。
正直、これは手を動かして考えたほうがよいと私は思いました。

正規表現 説明 使用例 例でマッチできる文字列 例でマッチできない文字列
(?!...)
否定先読み

... が次に続くものにマッチしなければマッチします。これは 否定先読みアサーション (negative lookahead assertion) です。例えば、abc (?!defg) は 'abc ' に、その後に 'defg' が続か ない 場合にのみ、マッチします。
abc(?!def) abcker,abc123,abc45g

abc~のものがマッチするがabcdefのみはマッチしない
abcdef,ab123,
(?=...)
肯定先読み
... が次に続くものにマッチすればマッチしますが、文字列をまったく消費しません。これは 先読みアサーション (lookahead assertion) と呼ばれます。例えば、abc (?=defg) は 'abc ' に、その後に 'defg' が続く場合にのみ、マッチします abc(?=def) abcdef,abcdefgh,12abcdef

abcdefの文字の配列があればマッチする。前後に何か文字がついても良い。
abdef,abcccc,ab123
(?<=...)
肯定後読み
その文字列における現在位置の前に、現在位置で終わる ... とのマッチがあれば、マッチします。これは 後読みアサーション と呼ばれます。(?<=abc)def は、後読みは 3 文字をバックアップし、含まれているパターンがマッチするか検査するので 'abcdef' にマッチを見つけます。含まれるパターンは、固定長の文字列にのみマッチしなければなりません。すなわち、 abc や a|b は許されますが、a* や a{3,4} は許されません。肯定後読みアサーションで始まるパターンは、検索される文字列の先頭とは決してマッチしないことに注意して下さい (?<=def)abc defabc,defabcd,123defabc

defabcの文字の配列があればマッチする。前後に何か文字がついても良い。
defagbc,def,defab,abc
(?<!...)
否定後読み
その文字列における現在位置の前に ... とのマッチがなければ、マッチします。これは 否定後読みアサーション(negative lookbehind assertion) と呼ばれます。肯定後読みアサーションと同様に、含まれるパターンは固定長の文字列にのみマッチしなければなりません。否定後読みアサーションで始まるパターンは検索される文字列の先頭でマッチできます。 (?<!abc)def abccdef,123def,g4defg,def

abcdefの配列の文字列が入っていないdefの文字列が入った文字がマッチになる
abcdef,abcdefg,12abcdefg

handson ~pythonの標準モジュールreを使って検証~

↓こちらは、search関数を使用しているため、文章中でもマッチする語を判定してくれます。

#標準モジュールreをインポート
import re
#変数:wordにinput関数を使用して、インプットした文字を格納します。
word = str(input())
#patternに検証する正規表現の文字列を入れていきます。
pattern = "te.t"
#reのsearch関数を使用して、検証します。
a = re.search(pattern, word)
print(a)

上記の検証コードの使用方法

  1. google colaboratoryをgoogleで検索して、アカウントを作成してください。
  2. 上記のコードを張り付けてください。
  3. patternの" "の中を検証したい正規表現の使用例におおきかえてください。
    例:pattern = "abcd*"
  4. 左上の再生マークを押すか、[ctrl]+[enter] で実行ができます。
     

Discussion