正規表現の前にエスケープシーケンスとは
- 正規表現の前にエスケープシーケンス(Escape Sequence)について。文字列には「文字として表記できない特別な文字」があります。例えば「改行」などです。
- 改行を表すのは \n (*1) ですが、これは 'n' という文字の前に '\' という特殊文字を付けることで、'n' という文字本来の意味を打ち消し(エスケープ)、'\' から続く文字との並び(シーケンス)に特別な意味を持たせます。これをエスケープシーケンスと呼びます。
- Pythonの文字列では、下記が代表的なエスケープシーケンスです。
エスケープシーケンス |
機能 |
\n | 改行 |
\r | 復帰(行先頭への移動) |
\t | タブ |
\b | バックスペース |
\\ | '\'文字自身(エスケープのエスケープ) |
\8進値 | 8進値コードで表される文字(例:\115=M') |
\x16進値 | 16進値コードで表される文字(例:\x4D='M') |
- 何故ここでエスケープシーケンスの話をしているかですが、前回の正規表現使用例からわかるように、正規表現は '\' を多用します。正規表現パターンを普通に文字列として記述すると、全てエスケープシーケンスと解釈されてしまうのです。
- Pythonでは、文字列リテラルの接頭に'r'を付けることで、文字列中のエスケープシーケンスを特別扱いせず「そのまま(raw)」の文字列と解釈します。raw文字列と呼びます。正規表現パターンはraw文字列による表記が便利です。
[Pythonコード例]
str_a = '改行\nと解釈される' # 普通の文字列
str_b = r'改行\nと解釈されない' # raw文字列
print('str_a =', str_a)
print('str_b =', str_b)
|
[出力]
str_a = 改行
と解釈される
str_b = 改行\nと解釈されない
|
正規表現のコンポーネント
- では本題に戻りましょう。前回からの続きで、正規表現のコンポーネントを見ていきます(*2)。
種別 |
コンポーネント |
文字クラス |
a abc ab|cd [abc] [a-z] [^ab]
\w \W \d \D \s \S .
|
量指定 |
* + ? {n} {min,} {min,max}
|
位置指定 |
^ $ \A \b \B
|
グループ化/参照 |
( ) (?: ) \1,\2...
|
先読み/後読みアサーション |
(?! ) (?= ) (?<! ) (?<= )
|
文字クラス
正規表現 |
例 |
説明 |
a |
re.search(r"a", "012abc") # マッチ
re.search(r"a", "012bcd") # None
|
文字'a'にマッチ |
abc |
re.search(r"abc", "012abcdef") # マッチ
re.search(r"abc", "012abdghi") # None
|
文字列'abc'にマッチ |
ab|cd |
re.search(r"ab|cd", "01abdef") # マッチ
re.search(r"ab|cd", "01acdfg") # マッチ
re.search(r"ab|cd", "01acbdi") # None
|
文字列'ab'又は'cd'にマッチ |
[abc] |
re.search(r"[abc]", "01adefg") # マッチ
re.search(r"[abc]", "012cdfg") # マッチ
re.search(r"[abc]", "01fghig") # None
|
文字'a','b'又は'c'にマッチ |
[a-z] |
re.search(r"[a-z]", "01-@y2") # マッチ
re.search(r"[a-z]", "01-@23") # None
|
文字'a'〜'z'にマッチ |
[^ab] |
re.search(r"[^ab]", "aabcab") # マッチ
re.search(r"[^ab]", "aabaab") # None
|
文字'a'又は'b'以外にマッチ
'^'は[]の外では違う意味に
|
\w |
re.search(r"\w", "--a @#") # マッチ
re.search(r"\w", "--! @#") # None
|
'_'と英数文字にマッチ
[a-zA-Z0-9_]と同じ
|
\W |
re.search(r"\W", "012#abc") # マッチ
re.search(r"\W", "012_abc") # None
|
'_'と英数文字以外にマッチ
[^a-zA-Z0-9_]と同じ
|
\d |
re.search(r"\d", "abc3def") # マッチ
re.search(r"\d", "abc.def") # None
|
数字にマッチ
[0-9]と同じ
|
\D |
re.search(r"\D", "012a456") # マッチ
re.search(r"\D", "0123456") # None
|
数字以外にマッチ
[^0-9]と同じ
|
\s |
re.search(r"\s", "abc def") # マッチ
re.search(r"\s", "abc.def") # None
|
空白文字にマッチ
[\n\r\t\f\v]と同じ
|
\S |
re.search(r"\S", "abcdef") # マッチ
re.search(r"\S", "\n") # None
|
空白文字以外にマッチ
[^\n\r\t\f\v]と同じ
|
. |
re.search(r".", " ") # マッチ
re.search(r".", "\n") # None
|
改行(\n)以外の全ての文字にマッチ
[^\n]と同じだがDOTALLモードでは扱い異なる
|
量指定
正規表現 |
例 |
説明 |
* |
re.search(r"ab*", "012acd") # マッチ
re.search(r"ab*", "012abc") # マッチ
re.search(r"ab*", "012bcd") # None
|
直前の正規表現'0'文字以上にマッチ |
+ |
re.search(r"ab+", "012abcd") # マッチ
re.search(r"ab+", "012abbc") # マッチ
re.search(r"ab+", "012bcde") # None
|
直前の正規表現'1'文字以上にマッチ |
? |
re.search(r"-?\d+", "-10") # マッチ
re.search(r"-?\d+", " 10") # マッチ
|
直前の正規表現'0'文字及び'1'文字にマッチ |
{n} |
re.search(r"\d{3}", "1000") # マッチ
re.search(r"\d{3}", " 10") # None
|
直前の正規表現'n'文字にマッチ |
{n,} |
re.search(r"\d{3,}", "1000") # マッチ
re.search(r"\d{3,}", " 10") # None
|
直前の正規表現'n'文字以上にマッチ |
{n,m} |
re.search(r"\d{3,4}", "100") # マッチ
re.search(r"\d{3,4}", "1000000") # マッチ
|
直前の正規表現
'n'文字以上、'm'文字以下にマッチ |
位置指定
正規表現 |
例 |
説明 |
^ |
re.search(r"^a", "abc012") # マッチ
re.search(r"^a", "012bcd") # None
|
文字列の先頭にマッチ
MULTILINEモードでは改行直後にもマッチ |
$ |
re.search(r"a$", "bc012a") # マッチ
re.search(r"a$", "012bcd") # None
|
文字列の末尾又は末尾改行直前にマッチ
MULTILINEモードでは改行直前にもマッチ |
\A |
re.search(r"\A\d", "1.23") # マッチ
re.search(r"\A\d", "e100") # None
|
文字列の先頭にのみマッチ |
\b |
re.search(r"\bRun\b", "On The Run") # マッチ
re.search(r"\bRun\b", "Running Away") # None
|
文字列の先頭/末尾/単語境界にマッチ
境界とは\w⇔\Wの変化点を指す
|
\B |
re.search(r"\BRun\B", "ImRunning") # マッチ
re.search(r"\BRun\B", "On The Run") # None
|
単語中の\wにマッチ
|
グループ化/参照
正規表現 |
例 |
説明 |
( ) |
re.search(r"(\w+),(\d+)", "FF,256") # マッチ
re.search(r"(\w+),(\d+)", "FF,ABC") # None
|
括弧内の正規表現にグループ化しつつマッチ
キャプチャ結果は後で参照/利用可能 |
(?: ) |
re.search(r"(?:\w+),(\d+)", "FF,256") # マッチ
re.search(r"(?:\w+),(\d+)", "FF,ABC") # None
|
括弧内の正規表現にグループ化しつつマッチ
しかしキャプチャしない |
\1,\2... |
re.search(r"(\d+),\1:(\w+)", "256,256:ABC") # マッチ
re.search(r"(\d+),\1:(\w+)", "256,128:abc") # None
|
指定グループ番号のキャプチャ結果を参照/利用
後方参照と呼ばれるが...参照で良いかと |
キャプチャ結果をプログラム内で利用する
- キャプチャ結果は正規表現内だけではなく当然プログラムからも利用できます。Pythonでの利用例を示します。
import re
# マッチ/キャプチャ結果をmatchオブジェクトで受け取る
o_match = re.search(r"(\d+),\1:(\w+)", "256,256:ABC")
# マッチ/キャプチャ時はo_matchオブジェクトに実体あるためTrue
if o_match:
print("group1:",o_match.group(1)) # \1 キャプチャ結果
print("group2:",o_match.group(2)) # \2 キャプチャ結果
else:
print("not matched")
group1: 256
group2: ABC
先読み/後読みアサーション
正規表現 |
例 |
説明 |
(?= ) |
re.search(r"(\w{3})(?=de)", "abcde") # マッチ
re.search(r"(\w{3})(?=de)", "abcef") # None
|
後続文字列が指定正規表現にマッチすることを見る
(?= )部はキャプチャされない |
(?! ) |
re.search(r"(\w{3})(?!de)", "abcef") # マッチ
re.search(r"(\w{3})(?!de)", "abcde") # None
|
後続文字列が指定正規表現にマッチしないことを見る
(?! )部はキャプチャされない |
(?<= ) |
re.search(r"(?<=ab)(\w{3})", "abcde") # マッチ
re.search(r"(?<=ab)(\w{3})", "cdefg") # None
|
前の文字列が指定正規表現にマッチすることを見る
(?<= )部はキャプチャされない |
(?<! ) |
re.search(r"(?<!ab)(\w{3})", "cdefg") # マッチ
re.search(r"(?<!ab)(\w{3})", "abcde") # None
|
前の文字列が指定正規表現にマッチしないことを見る
(?<! )部はキャプチャされない |
次回は正規表現オブジェクト/メソッド/フラグ設定について
- 正規表現はPython以外でも使用できる記述方法です。今回はその要素を羅列したため長くなってしまいました。
ですが忘れてしまうこともあるため、シートにまとめておくと「ぱっと見て」思い出せるようになります。
- 次回で正規表現の説明は終了予定ですが、Pythonとしての正規表現動作制御や、メソッドを扱いたいと思います。
|