2012-11-07 49 views
4

我有兩個文件Unix的多個字段加入兩個文件

貓test1.txt的

1|2|3|4 

2|3|4|4 

3|4|5|5 

貓的test2.txt

1|2|4|5 

2|3|5|6 

3|5|7|7 

我的輸出應該

1|2|3|4|4|5 

2|3|4|4|5|6 

它就像在字段1a上加入兩個文件nd 2並從文件1中獲得1,2,3,4的值,從文件2中獲得值。

請幫我這麼做嗎?

+0

這將是非常簡單的,如果你可以使用像sqlite這樣的數據庫 - 是一個選項嗎? –

回答

2

嘗試在perl

paste -d '|' file1.txt file2.txt | 
    perl -F'\|' -lane ' 
     print join "|", @F[0..3,6,7] if $F[0] eq $F[4] and $F[1] eq $F[5] 
    ' 

而且在sh這樣做:

#!/bin/sh 

paste -d '|' test1.txt test2.txt | while IFS='|' read a1 a2 a3 a4 a5 a6 a7 a8; do 
    if [ $a1 -eq $a5 -a $a2 -eq $a6 ]; then 
     echo "$a1|$a2|$a3|$a4|$a7|$a8" 
    fi 
done 

輸出

1|2|3|4|4|5 
2|3|4|4|5|6 
+0

你的最後一行是錯誤的,因爲這兩個表中都沒有匹配(應該與每個表中的前兩個字段相匹配) – DaveRlz

+0

@DaveRlz:OP不清楚他期望的最後一行 –

+0

@sputnick OP很漂亮明確。他們想要在兩個第一個字段上進行連接,這就解釋了爲什麼輸出中有兩行。 –

2

嗯,這爲您的示例工作:

sed 's/|/+/' t1.txt>$$.tmp;sed 's/|/+/' t2.txt|join -t \| -j 1 $$.tmp -|sed 's/+/|/';rm $$.tmp 
+1

無需臨時文件,您可以使用[進程替換](http://www.tldp.org/LDP/abs/html/process-sub.html):'sed ... |連接-t \ | -j 1 <(sed ...) - | ...' – huon

+0

現在我藉助一個新的有趣和有用的功能。 – pbhd

2

這也似乎工作:

$ sed 's/|/\t/2' 1.txt > 1_1.txt; sed 's/|/\t/2' 2.txt > 2_1.txt; 
$ join -j1 1_1.txt 2_1.txt | tr ' ' '|' 
$ rm 1_1.txt 2_1.txt 

一個班輪無需創建臨時文件(感謝@dbaupp):

$ join -j1 <(sed 's/|/\t/2' 1.txt) <(sed 's/|/\t/2' 2.txt) | tr ' ' '|' 
+1

無需臨時文件,您可以使用[進程替換](http://www.tldp.org/LDP/abs/html/process-sub.html):'join -j 1 <(sed ... )<(sed ...)| ...' – huon

+0

@dbaupp啊!我爲此瘋狂搜索,但不知道它是如何被調用的。謝謝! –

+0

哈哈,我曾經處於相同的位置!我知道我想做什麼,但是我不知道神奇的「過程替代」這個詞可以放進谷歌! – huon

5
awk -F\| 'NR == FNR { 
    f2[$1, $2] = $3 OFS $4 
    next 
    } 
($1, $2) in f2 { 
    print $0, f2[$1, $2] 
    }' OFS=\| test2.txt test1.txt 
+1

+1爲最佳解決方案。我會用BEGIN {FS = OFS =「|」},而不是單獨分配它們。 –

+0

謝謝埃德,謝謝你在Usenet上的所有有用的帖子和這裏在stackoverflow! –

+0

這很好。謝謝。 – user1807258

0

另一種解決方案:

awk -F "|" '{getline a < "file1"}NR==1{print a, $3, $4 "\n"}NR==3{print a, $3, $4}' OFS="|" file2 

結果:

$ awk -F "|" '{getline a < "file1"}NR==1{print a, $3, $4 "\n"}NR==3{print a, $3, $4}' OFS="|" file2 
1|2|3|4|4|5 

2|3|4|4|5|6