【Python 3系】re.sub() での置換方法

re.sub()での具体的な置換方法です。

 

【Python】文字列から<特定の文字列>を検索・抽出・置換・削除したい

 

 

re.sub() の構文

re.sub() の構文です。

[置換する回数]、[フラグ] はオプションです。

import re

re.sub('パターン(正規表現)', '置換後文字', '置換対象の文字列', [置換する回数], [フラグ])

 

re.sub() の正規表現は2種類ある

実は re.sub() には2パターンあります。

もし re.sub() で思った通りに置換されない場合は以下のパターンを確認してみてください。

 

■「r」を付けるパターン

#coding:utf-8
import re

 

info_old = 'java is language.'
print(info_old)

 

info_new = re.sub(r'java', 'javascript', info_old)
print(info_new)

 

【プログラムの実行結果】

java is language.
javascript is language.

 

 

■「r」を付けないパターン

#coding:utf-8
import re

 

info_old = 'java is language.'
print(info_old)

 

info_new = re.sub('java', 'javascript', info_old)
print(info_new)

 

【プログラムの実行結果】

java is language.
javascript is language.

 

 

「r」とは何か?

r は「raw」を表わしています。

Python の raw string 記法です。

rを付けると文字列内ではバックスラッシュ(\)を特別扱いしません。(つまりバックスラッシュそのままの文字であると認識される)

つまりエスケープシーケンスを省略できます。

通常「特殊文字(\'"など)」はバックスラッシュ(\)でエスケープする必要があります。

rを付けなくてもバックスラッシュを何度か付けたり消したりして動作確認をしてみれば最終的にはうまくいくと思いますが、それなら最初から「r」を付けた方がシンプルで思った通りの動きをすると思います。

 

6.2. re — 正規表現操作

https://docs.python.org/ja/3/library/re.html

 

公式サイトも raw string を使用することを推奨しています。

確かに以下の「Raw String記法」の解説を読むと r を付けないとバックスラッシュの数が増えて思わぬバグを生みそうです。

 

 

 

様々なパターン

■【失敗】「r」を付けないパターン

#coding:utf-8
import re

 

info_old = 'java is \\\language.'
print(info_old)

 

# \\\ を a に変換したい
info_new = re.sub('\\\', 'a ', info_old)
print(info_new)

 

■プログラム実行結果

エラーになります。

$ python test.py
  File "test.py", line 6
    info_new = re.sub('\\\', 'a ', info_old)
                              ^
SyntaxError: invalid syntax¶

 

 

 

■【失敗】「r」を付けるパターン

#coding:utf-8
import re

 

info_old = 'java is \\\language.'
print(info_old)

 

# \\\ を a に変換したい
info_new = re.sub(r'\\\', 'a ', info_old)
print(info_new)

 

■プログラム実行結果

同じくエラーになります。

$ python test.py
  File "test.py", line 6
    info_new = re.sub(r'\\\', 'a ', info_old)
                              ^
SyntaxError: invalid syntax¶

 

 

 

■【成功】「r」を付けるパターン

#coding:utf-8
import re

 

info_old = 'java is \\\language.'
print(info_old)

 

# \\\ を a に変換したい
info_new = re.sub(r'\\\\', 'a ', info_old) ← \ は4つでOK。最初の\がエスケープシーケンスとして効いて、残りの\\\を文字として扱う。
print(info_new)

 

■プログラム実行結果

こちらは想定の動きになりました。

$ python test9.py
java is \\language.
java is a language.

 

※よくよく考えてみたのですが、上の文字列は「\\language」と\が2つしか付いてません。

ということは \ 1つに対して \ 1つが対応している、ということで \ が 4つでうまくいくということです。

 

 

 

■【失敗】「r」を付けないパターン

#coding:utf-8
import re

info_old = 'java is \\\language.'
print(info_old)

# \\\ を a に変換したい
info_new = re.sub('\\\\\\', 'a ', info_old) ← r を付けないパターンで、単純に 6 つ \ をつなげればうまくいくと思いましたが。。。
print(info_new)

 

■プログラム実行結果

どうやら\に対して\を重ねればいいというような単純な話ではなさそうです。

$ python test.py
java is \\language.
Traceback (most recent call last):
  File "test.py", line 6, in 
    info_new = re.sub('\\\\\\', 'a ', info_old)
  File "/usr/lib64/python3.6/re.py", line 191, in sub
    return _compile(pattern, flags).sub(repl, string, count)
  File "/usr/lib64/python3.6/re.py", line 301, in _compile
    p = sre_compile.compile(pattern, flags)
  File "/usr/lib64/python3.6/sre_compile.py", line 562, in compile
    p = sre_parse.parse(p, flags)
  File "/usr/lib64/python3.6/sre_parse.py", line 855, in parse
    p = _parse_sub(source, pattern, flags & SRE_FLAG_VERBOSE, 0)
  File "/usr/lib64/python3.6/sre_parse.py", line 416, in _parse_sub
    not nested and not items))
  File "/usr/lib64/python3.6/sre_parse.py", line 488, in _parse
    sourceget()
  File "/usr/lib64/python3.6/sre_parse.py", line 255, in get
    self.__next()
  File "/usr/lib64/python3.6/sre_parse.py", line 245, in __next
    self.string, len(self.string) - 1) from None
sre_constants.error: bad escape (end of pattern) at position 2

 

 

■【成功】「r」を付けないパターン

#coding:utf-8
import re

info_old = 'java is \\\language.'
print(info_old)

# \\\ を a に変換したい
info_new = re.sub('\\\\\\\\', 'a ', info_old) ← \ を 8個付けるとうまくいきました。
print(info_new)

 

■プログラム実行結果

うまくいきました。

文字列に \\(\\\ではない)が入っていると考えればいいので、\ 1つに対して \ が 4つ必要ということになるのでしょうか。

これでは思いもよらない所でバグを引き起こしそうです。

$ python test9.py
java is \\language.
java is a language.

 

 

参考にしたサイト

6.2. re — 正規表現操作

https://docs.python.org/ja/3/library/re.html

 

 

 

Posted by 100%レンタルサーバーを使いこなすサイト管理人

コメントを残す

メールアドレスが公開されることはありません。