@mtujikawa (辻川 光也)

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

Pythonで辞書翻訳

Q&A

Closed

解決したいこと

Pythonでcsv辞書を使った置換(翻訳)のようなアプリをつくっています。
boy,男の子
のような単語のペアを羅列したcsv辞書を作り、それに基づき単語を置換していくだけのアプリです。
置換対象となるキーワードを見つけて1行づつ処理しています。
下のコードでは単純化のため、辞書の読み込みや辞書に基づく処理を消しています。

with open('sample.xml', 'r', encoding='UTF-8') as f:
    for line in f:
        if 'name=' in line:
            line = line.replace('boy', '男の子')
            print(line)  # (1)
    print(f)    # (2)
    data = f.read()
    print(data)    #(3)

上記コードで (1) の箇所では置換されていることが確認できるのですが、(2)のところでは

<_io.TextIOWrapper name='sample.xml' mode='r' encoding='UTF-8'>

と、なります。そこで、f.read()としたのですが、(3)では何も出力されません。

どなたかご教示いただければ幸いです。

自分で試したこと

最初はファイルをopenした直後に、data = f.read() して一括置換したのですが、意図しない箇所もマッチ、置換されてしまうため、1行ごとに置換対象行かどうか判断をするようにしました。

1行ごとの処理に関しては
https://qiita.com/niikura/items/8c792ba56877dfd5a31a
を参考にさせていただきました。

最初に f.read()する方法では以下コードを試しました。

with open('sample.xml', 'r', encoding='UTF-8') as f:
    data = f.read()
    for line in data.split('\n'):
        if 'name=' in line:
            line = line.replace('boy', '男の子')
            print(line)  # (1)
    print(data)    #(2)

このコードでは、(1)のところでは置換を確認できるのですが、(2)のところでは置換が反映されていません。
1行ごとに line で処理したものが、元の data に反映されていないようです。
こちらも理解が及びませんでした。

正規表現を使った re.sub() も試しました。
こちらは一応望んだ結果が得られたのですが、辞書の内容と完全一致しないと置換されず、"赤い帽子"を、”赤い"、"帽子"の2回に分けて置換することができず、辞書の整備が大変であることがわかりました。

ですので、str.replace() で処理したいと考えています。

よろしくお願いいたします。

1 likes

4Answer

こんにちは!
もしよろしければ、sample.xml のファイルの中身も載せていただけないでしょうか?
いまいち状況がつかめなくて...
すみませんが、頂けると幸いです!

0Like

Comments

  1. @mtujikawa

    Questioner

    以下のような感じで数千行あり、それが何十ファイルもあります。

    <?xml version="1.0" encoding="utf-8"?>
    <Main>
    <Composit>
    <Part>
    <name="Miracle Boy">
    </Part>
    <Part>
    <name="Miracle Girl">
    </Part>
    </Composit>
    </Main>

    置換したいのは name= の行だけなのです。

    よろしくお願いいたします。

以下のような感じで数千行あり、それが何十ファイルもあります。

<?xml version="1.0" encoding="utf-8"?>
<Main>
    <Composit>
        <Part>
          <name="Miracle Boy">
        </Part>
        <Part>
          <name="Miracle Girl">
        </Part>
    </Composit>
</Main>

置換したいのは name= の行だけなのです。

よろしくお願いいたします。

0Like

ありがとうございます!
メモリ等を考えるとあまりよろしくないですが、新たに文字列を生成してそこに全てアップデートしてみてはいかがでしょうか?
以下修正したコードです!

with open('sample.xml', 'r', encoding='UTF-8') as f:
    data = f.read()
    text = ""  # 新たな文字列用
    for line in data.split('\n'):
        if 'name=' in line:
            line = line.replace('boy', '男の子')
            print(line)  # (1)
        text += line + "\n"  # lineで一行ずつ読みだしているので、全行新たな文字列 text に結合していく
    print(text)    #(2)

0Like

Comments

  1. @mtujikawa

    Questioner

    回答ありがとうございます!
    新たに文字列を生成する方法はうまくいきました。

    しかし、なぜ元の data に手を入れられないのかが気になります。
  2. 良かったです!
    data は 2 行目で作成していて、それ以降は、line という変数で処理を行っているため、data が勝手に書き換わることはありませんね!
    あくまで data から抽出した line という別の変数を置換しただけなので!

コメントありがとうございます。
思いつきました。dataを書き換えればよいだけだったのですね。

with open('sample.xml', 'r', encoding='UTF-8') as f:
    data = f.read()
    for line in data.split('\n'):
        if 'name=' in line:
            line_r = line.replace('boy', '男の子')
            data = data.replace(line, line_r)
    print(data)

かなり強引な方法ですが、思っていた通りの動きになりました。
どうもありがとうございました。

0Like

Your answer might help someone💌