LoginSignup
23
17

More than 1 year has passed since last update.

正規表現で一致した文字列を取得し、置換のときに再利用する on Python3

Last updated at Posted at 2017-01-14

1.やりたいこと

Pythonの正規表現置換でマッチした文字列を置換に利用したい。
毎回忘れるのでメモ

2. 例えば?

英文解析で、こんなリストがあったとします。

英単語が入ったリスト
sentence = ['During', 'this', 'time', ',', 'many', 'chatterbots', 'were', 'written', 'including',
            'PARRY', ',', 'Racter', ',', 'and', 'Jabberwacky', '.']

これを(1文全体の)文字列にしたいな〜と思った時にまず考えつくのはjoinですよね。

半角スペース区切りでjoinしてみる
' '.join(sentence)
#During this time , many chatterbots were written including PARRY , Racter , and Jabberwacky .

はい…もう察しだと思われますが、.とか,とかの 前に半角スペース が入っています。
困りましたねぇ
じゃあどうするか…そうです。正規表現で置換しちゃえ!
でも,とか.とかどうやって置換しようか。

3. マッチした文字列を置換先で再利用

とりあえずやってみましょう。

英語の本文っぽく直す
import re

bad = ' '.join(sentence)
fixed = re.sub(r' ([,.])', r'\1', bad)
# r' [,.]' : 半角スペース+「,」「.」のどれか

print(fixed) 
出力
During this time, many chatterbots were written including PARRY, Racter, and Jabberwacky.

完成!

4.ちょっとだけ解説

re.sub を使う時、
第一引数のパターン文字列の中で、再利用したい部分を () で囲み
第二引数の文字列の置換したい部分に何番目の () を使いたいか「:1番目なら \1 」を指定します。
これを踏まえて、幾つか例を書いてみます。

check.py
bad = 'including PARRY , Racter , and Jabberwacky .'

# さっきのやつ
re.sub(r' ([,.])', r'\1', bad)
Out[4]: 'including PARRY, Racter, and Jabberwacky.'

# 「(」の場所が違う
re.sub(r'( [,.])', r'\1', bad)
Out[5]: 'including PARRY , Racter , and Jabberwacky .' # == bad

# 「()」でスペースを囲ってみる
re.sub(r'( )([,.])', r'\1', bad)
Out[6]: 'including PARRY  Racter  and Jabberwacky '

# 使う番目を変更
re.sub(r'( )([,.])', r'\2', bad)
Out[7]: 'including PARRY, Racter, and Jabberwacky.'

# 繋げて使ってみる
re.sub(r'( )([,.])', r'\1\2', bad)
Out[8]: 'including PARRY , Racter , and Jabberwacky .' # == bad

# 逆はどうか
re.sub(r'( )([,.])', r'\2\1', bad)
Out[9]: 'including PARRY,  Racter,  and Jabberwacky. ' # != bad

# 遊んでみる
re.sub(r'( )([,.])', r'\1ほげ\2', bad)
Out[12]: 'including PARRY ほげ, Racter ほげ, and Jabberwacky ほげ.'

補足

必ず '\num'の前にはrをつけてください。追記有り
良い例r'\1'
悪い例'\1'

追記(2017/01/19)

追加でバックスラッシュ\をつければrを付けなくても動くそうです。

コメントで教えてくださったshiracamusさんありがとうございます。

'\num'の場合はrを付ける必要がありますが、'\\num'にすればrを付けなくていいですよ。
r は raw(生=なま、未加工) の意味で、バックスラッシュをエスケープ文字として処理しない生(未加工)の文字列です。

>>> import re
>>> bad = 'including PARRY , Racter , and Jabberwacky .'
>>> re.sub(' ([,.])', '\\1', bad)
'including PARRY, Racter, and Jabberwacky.'

他にもおかしい点ありましたら、是非コメントにて教えて頂ける助かります。

23
17
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
23
17