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

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

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

Python 2.7は2.xシリーズでは最後のメジャーバージョンです。Python3.1にある機能の多くが含まれています。

Qt

QtはGUIプログラムの開発で広く使われているクロスプラットフォーム開発のフレームワークです。

正規表現

正規表現とは特定の文字列によるパターンマッチングを行う際に用いられる宣言型プログラミングです。

Python

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

Q&A

解決済

2回答

1346閲覧

Pythonの正規表現で一致した文字列を再利用したいがうまくいかない

mofu_mofu

総合スコア73

Python 2.7

Python 2.7は2.xシリーズでは最後のメジャーバージョンです。Python3.1にある機能の多くが含まれています。

Qt

QtはGUIプログラムの開発で広く使われているクロスプラットフォーム開発のフレームワークです。

正規表現

正規表現とは特定の文字列によるパターンマッチングを行う際に用いられる宣言型プログラミングです。

Python

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

1グッド

0クリップ

投稿2018/01/08 16:37

編集2018/01/08 16:44

###前提・実現したいこと
pythonとpyQtで作られているオープンソースのankiという単語帳アプリに検索して置換するという機能があり、そこでPythonの正規表現を使って単語帳の中身をある条件で置換をしたいのですがうまくいきません。

具体的には以下のように、置換前の「@@@の直後の1以上999以下の数値」を取得して置換後の文字列「<img src="hogehoge_xxx.png" />」のxxxに埋め込みたいです。このxxxは本のページ数です。以後この置換前の文字を便宜上サンプルとします。

#置換前のサンプル @@@123 @@@23 @@@34 @@@45 @@@56

#置換後のサンプル(この結果が欲しい) <img src="hogehoge_123.png" /> <img src="hogehoge_23.png" /> <img src="hogehoge_34.png" /> <img src="hogehoge_45.png" /> <img src="hogehoge_56.png" />

このように取得したいのですが、この123や23や34などを抽出したいときどのように書くのでしょうか?re.sub()\1を使用しても意図したようにいきませんでした。(参照:reモジュール)

###発生している問題・エラーメッセージ

上記サンプルを以下の画像のようにankiアプリ上で正規表現を使用して置換すると数字の一桁目だけが抽出されてしまいます。

イメージ説明

#置換前のサンプル @@@123 @@@23 @@@34 @@@45 @@@56
#置換後のサンプル(数字の最後の一桁だけ抽出される) img src="hogehoge_3.png" img src="hogehoge_3.png" img src="hogehoge_4.png" img src="hogehoge_5.png" img src="hogehoge_6.png"

上記の問題では置換をGUIで実行していますが、ankiのソースコードのl.497のrepl関数を見る限り、pythonではおそらく以下のようなことをしていると考えています。しかし私のpowershell上での実行結果は適切に表示されず、確認できない状態になってしまっています。ただ、適切に表示されない部分(=)が一文字なので置換後のサンプルと多分同じ挙動だと思われます。

#resub.py import re regex = re.compile("@@@(\d){1,3}") reSub = re.sub(regex,"img src=hogehoge_\1.png","@@@123\n@@@23\n@@@34\n@@@45\n@@@56\n") print(reSub)
PS > python -V Python 2.7.14 PS > python .\resub.py img src=hogehoge_.png img src=hogehoge_.png img src=hogehoge_.png img src=hogehoge_.png img src=hogehoge_.png

###該当のソースコード

ankiのソースコードのfindReplace関数(l.481からl.528)で検索して置換するを実装をしていると思われます。

###試したこと

①サンプルを置換文字列\2で実行 → 無効な処理と表示される(おそらくエラー)
イメージ説明

②サンプルを置換文字列\0で実行 → サンプルがすべて消える
イメージ説明

③サンプルを置換文字列\1\1\1で実行
イメージ説明

#③の結果 333 333 444 555 666

###補足情報(言語/FW/ツール等のバージョンなど)
Windows10
Python2系

以上になりますがどうぞよろしくお願いいたします。

umyu👍を押しています

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

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

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

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

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

guest

回答2

0

ベストアンサー

数字をマッチさせたいならこうでは?

Python

1regex = re.compile("@@@(\d){1,3}")

Python

1regex = re.compile("@@@(\d{1,3})")

正規表現はオンラインの可視化サイト Regex101を見ながら作成するのが一番ミスがないかと。

投稿2018/01/08 16:50

umyu

総合スコア5846

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

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

mofu_mofu

2018/01/08 16:57

umyuさんのおっしゃるとおり```@@@(\d){1,3}```ではなく```@@@(\d{1,3})```でした。 意図した数字を取得することができました。 迅速な対応本当にありがとうございます。
umyu

2018/01/08 16:59

解決おめでとうございます。 明確な質問だったので、回答しやすかったです。
guest

0

正解はumyuさんが書いておられるとおりでしょう。

()はその中に書いてある正規表現にマッチする部分を取り出すもの。そして\dは数字一文字にマッチするもの。

従って、(\d){1,3}では、()はその後に書いてある量指定子{1,3}のことなど気にもせず\dにマッチするものすなわち数字一文字を取ってきます。

()にマッチした部分文字列は\1とか\2とかで指定できるわけですが、この数字は開括弧が現れた順番に一致します。たとえばabcdefという文字列に対して(.).(.).((.).)という正規表現をマッチさせると、\1,\2,\3,\4にそれぞれa c ef e が入ります。試したこと①のようにすれば\0は無いので結果は空になるし、試したこと②のようにすれば当然333のような結果が返って来てしまいます。

投稿2018/01/08 17:07

KojiDoi

総合スコア13671

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

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

mofu_mofu

2018/01/12 07:07

お礼が遅れてしまい申し訳ありません。 \数字は何番目のカッコの内容を取得するのかという意味で、私が設定した()が一つしかないので\1以外意味なかったのですね。 そして、量指定子が()外にあるので1個から3個までという意味が()に適用されていないのですね。 大変勉強になりました。ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問