の後の各単語を置き換えようとしています。以下の txt ファイル内:
line1
line2
field: [orders.cancelled,orders.delivered,orders.reached
orders.pickup,orders.time]
some line
some line
私は辞書を持っています:
d = {'cancelled':'cancelled_at', 'deliver':'xxx'}
次のコードを実行しています。ただし、部分一致の結果が得られます。つまり
新しいファイルには次の単語が含まれています。
field: [orders.cancelled_at, orders.xxxed ..........
ここでは、delivered という単語から、プログラムはまだ最初の 7 単語 (deliver) を置き換え、最後に 'ed' を追加しています。理由はわかりません
with open('list.txt', 'r') as g:
text = g.read()
for k in d:
before = f'.{k}'
after = f'.{d[k]}
#print(before)
#print(after)
text = text.replace(before, after)
#print(text)
with open('new_list.txt', 'w') as w:
w.write(text)
これも試してみましたが、同じ結果が得られました。
import re
with open('list.txt', 'r') as f:
text = f.read()
for k in d:
before = f'.{k}(?!=\w)'
print(before)
after = f'.{d[k]}'
print(after)
text = re.sub(before, after, text)
with open('new_list.txt', 'w') as w:
w.write(text)
deliver という単語を xxx に置き換えています。。結果はxxxedになります。 「配信済み」を追加: 「xxx」
– スパイララボ
2020 年 9 月 3 日 11:43
1) 単語境界を使用して単語全体と一致させます。2) エスケープします。文字クラスの外でリテラルと一致します。
– Wiktor Stribiżew
2020 年 9 月 3 日 11:46
@spyralab キーに価値を「届ける」 「配信」されていません。完全に一致するものが見つからない場合、プログラムは何も変更しないことを期待します。この場合、新しい行はorders.canceled_at、orders._delivered
として追加されるはずです。
– 兆
2020 年 9 月 3 日 11:50
f'\b{k}\b' - これはうまくいくはずです? @WiktorStribiżew 申し訳ありませんが、正規表現についてはあまり詳しくないので、詳しく説明していただければ幸いです。
– 兆
2020 年 9 月 3 日 11:54
1
\b 単語境界は、文字列内に単語全体が含まれる場合にのみ一致する必要があるため、short\b は short に一致します。ショートパンツではありません。
– Wiktor Stribiżew
2020 年 9 月 7 日 12:06
------------------------
使用できます
import re
d = {'cancelled':'cancelled_at', 'deliver':'xxx'}
rx = re.compile(fr"(?<=\.)(?:{'|'.join(d)})\b")
with open('list.txt', 'r') as f:
print( re.sub(rx, lambda x: d[x.group()], f.read()) )
Python のデモを見る
コードによって生成される正規表現は次のようになります
(?<=\.)(?:cancelled|deliver)\b
正規表現のデモをご覧ください。詳細:
(?<=\.) - リテラルの直前にある位置と一致する肯定的な後読み。
(?:キャンセル|配信) - 2 つの選択肢: キャンセルまたは配信
\b - wとしてホールワード、\b はワード境界です。
ラムダ x: d[x.group()] 置換は、一致した単語を対応する辞書キー値に置き換えます。
2
「f」をどのような場合に使用するのか説明してもらえますか? 「前」 , re.complie で fr を使用していることがわかります。それらの違いを説明していただければ幸いです。
– 兆
2020 年 9 月 4 日 15:23
1
@HamzaShehzad r は、文字列リテラルを定義するために使用される生の文字列リテラル プレフィックスであり、バックスラッシュは文字列のエスケープ シーケンスの形成に使用されません (正規表現は regex101.com で動作しますが、prod では動作しません) の上部のボーナス セクションをお読みください)糸。 f は、変数補間 (または変数拡張) の使用を可能にする f 文字列プレフィックスです。つまり、(str.format を使用する代わりに) 手動で追加した文字列と変数を実際に連結するには、文字列リテラル内で {varname} を使用します。
– Wiktor Stribiżew
2020 年 9 月 4 日 16:24