Python正規表現における特殊文字のエスケープ
特殊文字を文字そのものとして扱いたいとします。 そのためには、バックスラッシュでエスケープする必要があります。 例を見てみましょう。
例
次の例で、正規表現の作者は検索パターンを
文字
'a'、次にプラス記号'+'、次に
文字'x'のようにしたかったのです。
しかし、コードの作者は記号'+'を
エスケープしなかったため、実際の検索パターンは
次のようになっています:文字'a'が
1回以上、その後文字'x':
txt = 'a+x ax aax aaax'
res = re.sub('a+x', '!', txt)
print(res)
コード実行結果:
'a+x ! ! !'
例
今度は、作者がプラス記号をバックスラッシュで
エスケープしました。
これで検索パターンは意図した通りになります:
文字'a'、次にプラス記号'+'、
次に文字'x':
txt = 'a+x ax aax aaax'
res = re.sub('a\+x', '!', txt)
print(res)
コード実行結果:
'! ax aax aaax'
例
この例では、パターンは次のようになります:
文字'a'、次にドット'.'、
次に文字'x':
txt = 'a.x abx azx'
res = re.sub('a\.x', '!', txt)
print(res)
コード実行結果:
'! abx azx'
例
次の例では、作者はスラッシュをエスケープするのを 忘れ、正規表現がすべての部分文字列に マッチしてしまいました。エスケープされていない ドットは任意の文字を意味するからです:
txt = 'a.x abx azx'
res = re.sub('a.x', '!', txt)
print(res)
コード実行結果:
'! ! !'
注意点
ドットをエスケープするのを忘れた場合(ドットが それ自身を表すべきときに)、それに気づかない 可能性さえあることに注意してください:
res = re.sub('a.x', '!', 'a.x')
print(res) # '!' を返します。意図した通りです。
見た目は正しく動作しています(ドットは任意の文字、
通常のドット'.'も含めて表すため)。
しかし、置換を行う文字列を変更すると、エラーが
わかります:
res = re.sub('a.x', '!', 'a.x abx azx')
print(res) # '! ! !' を返しますが、期待は '! abx azx' でした。
特殊文字と通常文字のリスト
通常の文字をエスケープしても、問題はありません - それは依然としてそれ自身を表します。 例外は数字で、それらはエスケープできません。
ある文字が特殊文字かどうか疑問に思うことが よくあります。疑わしい文字を片っ端から エスケープする人もいます。 しかし、これは悪い習慣です (正規表現をバックスラッシュで乱雑にするため)。
特殊文字:$ ^ . * + ? \ / {} [] () |
特殊文字ではないもの:@ : , ' " - _ = < > % # ~ `& !
実践問題
次の文字列が与えられます:
txt = 'a.a aba aea'
'a.a' という文字列を見つけ、他を
取り込まない正規表現を書いてください。
次の文字列が与えられます:
txt = '2+3 223 2223'
'2+3' という文字列を見つけ、他を
取り込まない正規表現を書いてください。
次の文字列が与えられます:
txt = '23 2+3 2++3 2+++3 345 567'
'2+3'、'2++3'、
'2+++3' という文字列を見つけ、
他を取り込まない正規表現を書いてください
(+の数は任意)。
次の文字列が与えられます:
txt = '23 2+3 2++3 2+++3 445 677'
'23'、'2+3'、
'2++3'、'2+++3'
という文字列を見つけ、他を取り込まない
正規表現を書いてください。
次の文字列が与えられます:
txt = '*+ *q+ *qq+ *qqq+ *qqq qqq+'
'*q+'、'*qq+'、
'*qqq+' という文字列を見つけ、
他を取り込まない正規表現を書いてください。
次の文字列が与えられます:
txt = '[abc] {abc} abc (abc) [abc]'
角括弧内の文字列を見つけ、'!'に
置き換える正規表現を書いてください。