2017-06-20 1 views
0

複数の行のレコードを含む構造化テキストファイルがあります。各レコードにはキー固有のフィールドが必要です。私は、一連のこれらのファイルを読んで、一意でないキーフィールドを見つけてキー値を一意の値に置き換える必要があります。正規表現を使用してテキストファイル内の複数のエンティティを置換する

私のスクリプトは、置き換えが必要なすべてのフィールドを識別しています。これらのフィールドは、キーが一意でないフィールドである辞書に格納され、値は一意の値のリストです。

例:私は「1111111111」(dictのキー)と、最初のキー値を持つ最初のマッチを置き換えるのインスタンスを見つけ、一度だけ、各ファイルを介して読み込まれやりたい何

{ 
"1111111111" : ["1234566363", "5533356775", "6443458343"] 
} 

、2試合目2番目のキー値を持つなど

私は正規表現を使用しようとしていますが、私は、ファイルをループせずに、適切なREを構築する方法を確認していない複数回

これは私の現在のコードです:

def multireplace(Text, Vars): 
    dictSorted = sorted(Vars, key=len, reverse=True) 
    regEx = re.compile('|'.join(map(re.escape, dictSorted))) 
    return regEx.sub(lambda match: Vars[match.group(0)], Text) 

text = multireplace(text, find_replace_dict) 

これは、単一のキーのために正常に動作します:値の組み合わせが、場合、コンパイルに失敗します:値がリストである:

return regEx.sub(lambda match: Vars[match.group(0)], Text , 1) 
TypeError: sequence item 1: expected str instance, list found 

ファイルを介して複数回ループすることなく、機能を変更することができますか?

答えて

1

コメントを読んでコメントを読んでください。

import re 

def replace(text, replacements): 
    # Make a copy so we don't destroy the original. 
    replacements = replacements.copy() 

    # This is essentially what you had already. 
    regex = re.compile("|".join(map(re.escape, replacements.keys()))) 

    # In our lambda, we pop the first element from the array. This way, 
    # each time we're called with the same group, we'll get the next replacement. 
    return regex.sub(lambda m: replacements[m.group(0)].pop(0), text) 

print(replace("A A B B A B", {"A": ["A1", "A2", "A3"], "B": ["B1", "B2", "B3"]})) 

# Output: 
# A1 A2 B1 B2 A3 B3 

UPDATE以下のコメントで問題を支援するために、文字列は代替品を使い果たし正確に教えてくれます、このバージョンを試してみてください

:何も意味がありませんなら、私を知ってみましょう:リターンregex.sub(ラムダメートルを:代替品[m.group(0)](0)、テキストをポップ。)

import re 

def replace(text, replacements): 

    # Let's make a method so we can do a little more than the lambda. 
    def make_replacement(match): 
     try: 
      return replacements[match.group(0)].pop(0) 
     except IndexError: 
      # Print out debug info about what happened 
      print("Ran out of replacements for {}".format(match.group(0))) 
      # Re-raise so the process still exits. 
      raise 

    # Make a copy so we don't destroy the original. 
    replacements = replacements.copy() 

    # This is essentially what you had already. 
    regex = re.compile("|".join(map(re.escape, replacements.keys()))) 

    # In our lambda, we pop the first element from the array. This way, 
    # each time we're called with the same group, we'll get the next replacement. 
    return regex.sub(make_replacement, text) 

print(replace("A A B B A B A", {"A": ["A1", "A2", "A3"], "B": ["B1", "B2", "B3"]})) 

# Output: 
# A1 A2 B1 B2 A3 B3 
+0

これで私のために失敗している はIndexErrorを:空のリスト私は取得しています – theObserver

+0

からポップopを含むファイルからのテキストen(full_file_path、 'r')をf:text = f.read()として返します。その後、dictを使ってreplace関数にテキストを渡します。あなたのコードは1行のテキストではうまくいくようです。 – theObserver

+0

'IndexError:pop from empty list'を取得している場合は、その特定の文字列の置換えが不足しているようです。 (それらはすべて既に使用されていました) – smarx

関連する問題