2012-05-05 41 views
5

我有以下格式兩個文本文件中的文本處理:有兩個文件

首先是這對每行:

Key1:Value1

二是這樣的:

Key2:Value2

有沒有一種方法可以代替Value1file1Value2從使用它作爲密鑰獲得file2

例如:

文件1:

foo:hello 
bar:world 

文件2:

hello:adam 
bar:eve 

我想獲得:

foo:adam 
bar:eve 

不一定有之間的匹配每個李上的兩個文件東北。這可以在awk或其他東西中整齊地完成,還是我應該在Python中天真地做到這一點?

回答

3

創建兩個詞典,每個文件一個。例如:

file1 = {} 
for line in open('file1', 'r'): 
    k, v = line.strip().split(':') 
    file1[k] = v 

或者如果你喜歡一個班輪:

file1 = dict(l.strip().split(':') for l in open('file1', 'r')) 

然後,你可以這樣做:

result = {} 
for key, value in file1.iteritems(): 
    if value in file2: 
     result[key] = file2[value] 

另一種方法是你可以生成鍵值反向配對file1並使用set。例如,如果你的file1包含foo:bar,你的file1字典是{bar: foo}

for key in set(file1) & set(file2): 
    result[file1[key]] = file2[key] 

基本上,你可以快速找到使用交集共同的元素,因此這些元素保證在文件2,你不要浪費時間檢查它們的存在。

編輯:正如@pepr指出如果訂單對您很重要,您可以使用collections.OrderedDict作爲第一種方法。

+2

可能'collections.OrderedDict'(Python 2.7+和3.1+)可能是一個選項,以原始順序將值寫回文件(如果要寫回)。 [我不喜歡給字典的** fileX **名字。此外,打開的文件應該比運行時更早關閉。] – pepr

+0

好點,我沒有想過這個命令。 – spinlok

0

一旦你有:

file1 = {'foo':'hello', 'bar':'world'} 
file2 = {'hello':'adam', 'bar':'eve'} 

你可以做一個醜陋的一個班輪:

print dict([(i,file2[i]) if i in file2 else (i,file2[j]) if j in file2 else (i,j) for i,j in file1.items()]) 
{'foo': 'adam', 'bar': 'eve'} 

如在你的榜樣,你在file2同時使用的file1keysvalueskeys

0

如果你不考慮使用基本的Unix/Linux命令作弊,那麼這裏是一個使用paste和awk的解決方案。

paste file1.txt file2.txt | awk -F ":" '{ print $1":"$3 }'

+0

該解決方案假定'file1'中的鍵控數據在文件的同一行號上找到,該文件與引用發生處'file2'中的行號一致。假設在給定的小樣本數據中,這恰好是巧合的,這是合理的。 – Kaz

1
join -t : -1 2 -2 1 -o 0 2.2 -a 2 <(sort -k 2 -t : file1) <(sort file2) 

輸入文件必須在他們加入了對字段排序。

選項:

  • -t : - 使用冒號作爲分隔符
  • -1 2 - 加入對文件1
  • -2 1場2 - 加入的文件2
  • -o 0 2.2場1 - 從file2輸出連接字段後跟字段2(用分隔符分隔)
  • -a 2 - 輸出未連接的行從文件2
2

awk的解決方案:

awk ' 
    BEGIN {FS = OFS = ":"} 
    NR==FNR {val[$1] = $2; next} 
    $1 in val {$2 = val[$1]} 
    {print} 
}' file2 file1 
0

這可能會爲你(可能是GNU SED)工作:

sed 's#\([^:]*\):\(.*\)#/\\(^\1:\\|:\1$\\)/s/:.*/:\2/#' file2 | sed -f - file1 
0

TXR:

@(next "file2") 
@(collect) 
@key:@value1 
@ (cases) 
@ (next "file1") 
@ (skip) 
@value2:@key 
@ (or) 
@ (bind value2 key) 
@ (end) 
@ (output) 
@value2:@value1 
@ (end) 
@(end) 

運行:

$ txr subst.txr 
foo:adam 
bar:eve