質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

2回答

730閲覧

Python 正規表現でマッチした部分をリスト順に置換したいです

kero16

総合スコア9

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2019/12/01 01:30

前提・実現したいこと

正規表現でマッチしたhref属性を
リスト[0]→[1]→[2]の順に置換したいと考えています。

以下の方法では、すべてリスト[0]に置換されてしまいます。
ご教示いただければ幸いです。何卒よろしくお願いいたします。

(前回、BeautifulSoupでzipを使った置換方法を教えていただきました。
https://teratail.com/questions/225332
今回は、htmlではないテキスト文書を置換する場合を考えたところ(サンプルはhtmlですが)
zipを使ったもの、そうでないものを考えたのですが行き詰ってしまい、また相談をさせていただいた次第です。
よろしくお願いいたします。)

該当のソースコード

html

1<!-- リスト afters = ['after_11', 'after_24', 'after_32']--> 2 3<body> 4 5<a href="https://www.nochange.com/"></a> <!-- →変更しない --> 6 7<div class="sample"> 8 <a href="https://www.change.com/before_a/test"></a> <!-- →https://www.change.com/リスト[0]/test に変更--> 9</div> 10<div class="sample"> 11 <a href="https://www.change.com/before_b/test"></a><!-- →https://www.change.com/リスト[1]/test に変更--> 12</div> 13<div class="sample"> 14 <a href="https://www.change.com/before_c/test"></a><!-- →https://www.change.com/リスト[2]/test に変更--> 15</div> 16 17<a href="https://www.none.com/"></a><!-- →変更しない --> 18 19</body>

python

1import re 2from pathlib import Path 3 4PATH = '/Users/○○/test.html' 5afters = ['after_11', 'after_24', 'after_32'] 6 7def changeurl(m): 8 for after in afters: 9 return f'https://www.change.com/{after}/test' 10 11html = Path(PATH) 12 13html_text = html.read_text() 14 15after_html = re.sub(r'https://www.change.com/[A-Za-z0-9_]+/test', changeurl, html_text) 16 17 18"""結果:すべてリスト[0]に置換されてしまいます。 19print(after_html) 20<body> 21 22<a href="https://www.nochange.com/"></a> 23 24<div class="sample"> 25 <a href="https://www.change.com/after_11/test"></a> 26</div> 27<div class="sample"> 28 <a href="https://www.change.com/after_11/test"></a> 29</div> 30<div class="sample"> 31 <a href="https://www.change.com/after_11/test"></a> 32</div> 33 34<a href="https://www.none.com/"></a> 35 36</body>"""

python

1#zipを使ったこちらの内容も、希望する結果となりませんでした 2import re 3from pathlib import Path 4 5PATH = '/Users/○○/test.html' 6afters = ['after_11', 'after_24', 'after_32'] 7pattern = r'https://www.change.com/([A-Za-z0-9_]+)/test' 8 9html = Path(PATH) 10html_text = html.read_text() 11 12matchs = re.finditer(pattern, html_text) 13 14for match, after in zip(matchs, afters): 15 after_html = re.sub(r'https://www.change.com/[A-Za-z0-9_]+/test', after, match.group()) 16 17 18"""結果 19print(after_html) 20after_11 21after_24 22after_32

補足情報(FW/ツールのバージョンなど)

Python 3.6.5

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

文字位置を得て、そこで切ってつなぎ変えます。

Python

1after_html = html_text 2for match, after in zip(matchs, afters): 3 after_html = after_html[:match.start(1)] + after + after_html[match.end(1):]

投稿2019/12/01 03:06

otn

総合スコア84505

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kero16

2019/12/01 03:45

ご回答ありがとうございます。できました!! [:match.start(1)] と after と after_html[match.end(1):]をひとつずつprintで確認して 考えていたらお礼のコメントが遅くなってしまいました。すみません。 文字位置を取得するという方法を知ることができました。 ありがとうございました。
otn

2019/12/01 03:50

Rubyっぽく、 after_html[match.span(1)] = after とか書ければシンプルなのですが、Pythonだとできません。
guest

0

ベストアンサー

クロージャを利用してやるのはどうでしょう。

Python

1def make_change_url(afters): 2 it = iter(afters) 3 def change_url(m): 4 after = next(it) 5 return f'https://www.change.com/{after}/test' 6 7 return change_url 8 9... 10 11after_html = re.sub( 12 r'https://www.change.com/[A-Za-z0-9_]+/test', 13 make_change_url(afters), 14 html_text 15)

また正規表現を工夫すると、同じような文字列を複数回打たずに済みます。

Python

1def make_change_url(afters): 2 it = iter(afters) 3 def change_url(m): 4 return next(it) 5 6 return change_url 7 8... 9 10after_html = re.sub( 11 r'(?<=https://www.change.com/)[A-Za-z0-9_]+(?=/test)', 12 make_change_url(afters), 13 html_text 14)

投稿2019/12/01 02:26

LouiS0616

総合スコア35660

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kero16

2019/12/01 02:58

ご回答ありがとうございます。無事できました!! クロージャという存在を初めて知ることができました。 これから改めて調べ、勉強します。 正規表現も1度で済むこのような書き方があるのですね。 教えてくださりありがとうございます。 (?<=) と (?=) を使う・・という方法も調べてみます。 本当にありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問