2012-11-07 22 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