使用awk混合两个文件

时间:2013-03-20 03:06:21

标签: linux awk

我有两个制表符分隔文件

file1.txt

field1
field2
field3

file2.txt

field1   value f11
field1   value f12
field1   value f13
field2   value f21
field2   value f22
field2   value f23
field3   value f31

我想要输出

field1   value f11, value f12 , valuef13
field2   value f21, value f22 , valuef23
field3   value f31

我正在尝试这个

awk -F"\t" 'NR==FNR{a[$1] = $1;next} { print a[$1]  }' file1.txt file2.txt

它将变为空

如果filds在file1中而不在file2中,那么它应该是comas blank

更新:

这是我的终端输出

    ubuntu@ubuntu:/mnt/coding/awk$ cat f1.txt 
    field1
    field2
    field3
    field9

    ubuntu@ubuntu:/mnt/coding/awk$ cat f2.txt 
    field1  value f11
    field1  value f12
    field1  value f13
    field2  value f21
    field2  value f22
    field2  value f23
    field3  value f31

    ubuntu@ubuntu:/mnt/coding/awk$ awk -F"\t" 'NR==FNR{a[$1] = a[$1]", "$2;next}{gsub("^,","",a[$1]);print $1"\t"a[$1]}' f2.txt f1.txt
    field1  
    field2  
    field3  
    field9  

    ubuntu@ubuntu:/mnt/coding/awk$ awk --version
GNU Awk 3.1.8
Copyright (C) 1989, 1991-2010 Free Software Foundation.

更新2:

ubuntu@ubuntu:/mnt/coding/awk$ od -xcb f1.txt
0000000    6966    6c65    3164    660a    6569    646c    0a32    6966
          f   i   e   l   d   1  \n   f   i   e   l   d   2  \n   f   i
        146 151 145 154 144 061 012 146 151 145 154 144 062 012 146 151
0000020    6c65    3364    660a    6569    646c    0a39    000a
          e   l   d   3  \n   f   i   e   l   d   9  \n  \n
        145 154 144 063 012 146 151 145 154 144 071 012 012
0000035
ubuntu@ubuntu:/mnt/coding/awk$ od -xcb f2.txt
0000000    6966    6c65    3164    2020    6176    756c    2065    3166
          f   i   e   l   d   1           v   a   l   u   e       f   1
        146 151 145 154 144 061 040 040 166 141 154 165 145 040 146 061
0000020    0a31    6966    6c65    3164    2020    6176    756c    2065
          1  \n   f   i   e   l   d   1           v   a   l   u   e    
        061 012 146 151 145 154 144 061 040 040 166 141 154 165 145 040
0000040    3166    0a32    6966    6c65    3164    2020    6176    756c
          f   1   2  \n   f   i   e   l   d   1           v   a   l   u
        146 061 062 012 146 151 145 154 144 061 040 040 166 141 154 165
0000060    2065    3166    0a33    6966    6c65    3264    2020    6176
          e       f   1   3  \n   f   i   e   l   d   2           v   a
        145 040 146 061 063 012 146 151 145 154 144 062 040 040 166 141
0000100    756c    2065    3266    0a31    6966    6c65    3264    2020
          l   u   e       f   2   1  \n   f   i   e   l   d   2        
        154 165 145 040 146 062 061 012 146 151 145 154 144 062 040 040
0000120    6176    756c    2065    3266    0a32    6966    6c65    3264
          v   a   l   u   e       f   2   2  \n   f   i   e   l   d   2
        166 141 154 165 145 040 146 062 062 012 146 151 145 154 144 062
0000140    2020    6176    756c    2065    3266    0a33    6966    6c65
                  v   a   l   u   e       f   2   3  \n   f   i   e   l
        040 040 166 141 154 165 145 040 146 062 063 012 146 151 145 154
0000160    3364    2020    6176    756c    2065    3366    0a31    000a
          d   3           v   a   l   u   e       f   3   1  \n  \n
        144 063 040 040 166 141 154 165 145 040 146 063 061 012 012
0000177
ubuntu@ubuntu:/mnt/coding/awk$ 

其他:

awk -F"\t" 'NR==FNR{a[$1] = a[$1]", "$2; print "["$1"/"$2"]"; next}{gsub("^,","",a[$1]);print $1"\t"a[$1]}' f2.txt f1.txt
[field1  value f11/]
[field1  value f12/]
[field1  value f13/]
[field2  value f21/]
[field2  value f22/]
[field2  value f23/]
[field3  value f31/]
[/]
field1  
field2  
field3  
field9  

2 个答案:

答案 0 :(得分:4)

这是一个可能的解决方案:

NR==FNR{a[$1]=a[$1]", "$2;next}{gsub("^,","",a[$1]);print $1"\t"a[$1]}

这首先将键和值存储在file2中,然后处理file1以输出它们。以下(略有格式化的)成绩单显示了这一点:

pax> cat file1.txt

field1
field2
field3
field9

pax> cat file2.txt

field1  value f11
field1  value f12
field1  value f13
field2  value f21
field2  value f22
field2  value f23
field3  value f31

pax> awk -F"\t" 'NR == FNR{
...>                 a[$1] = a[$1]", "$2;
...>                 next
...>             }
...>             {
...>                 gsub ("^,", "", a[$1]);
...>                 print $1"\t"a[$1]
...>             }' file2.txt file1.txt 

field1   value f11, value f12, value f13
field2   value f21, value f22, value f23
field3   value f31
field9

根据您的更新,我建议您使用sed命令print "["$1"/"$2"]"并获得:

[field1  value f11/]
[field1  value f12/]
[field1  value f13/]
[field2  value f21/]
[field2  value f22/]
[field2  value f23/]
[field3  value f31/]

表示这些字段以制表符分隔。 od命令的输出也证实了这一点,您可以清楚地看到2020两个空格序列。

您需要对其进行排序,否则命令将无法与-F"\t"一起使用。例如,如果我使用空格替换file2.txt中的每个标签,我会看到您所看到的内容:

pax> awk -F"\t" 'NR==FNR{a[$1] = a[$1]", "$2;next}
...>   {gsub("^, ","",a[$1]);print $1"\t"a[$1]}' file2.txt file1.txt 
field1  
field2  
field3  
field9  

所以,你需要做出决定:

  • 修改文件,使其标签分隔;或
  • 修改awk选项以使用实际文件格式。

鉴于你在线上的其他地方有空格,第一个选项可能是最简单的。要修改文件以使用选项卡替换每行上的第一组空格,可以使用:

sed 's/  */\t/' file2.txt >file2a.txt
mv file2a.txt file2.txt                 # once you're happy.

(或使用GNU -i的{​​{1}}现场编辑选项。

答案 1 :(得分:0)

使用其他工具而不是awk(并假设有一个选项卡将字段与file2中的值分开):

for f in `cat /tmp/file1.txt`; do grep $f /tmp/file2.txt | cut -f2- | paste -s -d, | sed "s/^/$f\t/g" ; done

(我已将此作为评论发布,但似乎无法在评论中逃避反对)