2013-03-20 90 views
0

我有两个制表符分隔文件使用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在文件1,而不是在文件2那么就应该昏迷空白

UPDATE:

这是从我的终端

我的输出
[email protected]:/mnt/coding/awk$ cat f1.txt 
    field1 
    field2 
    field3 
    field9 

    [email protected]:/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 

    [email protected]:/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 

    [email protected]:/mnt/coding/awk$ awk --version 
GNU Awk 3.1.8 
Copyright (C) 1989, 1991-2010 Free Software Foundation. 

UPDATE 2:

[email protected]:/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 
[email protected]:/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 
[email protected]:/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 
+0

那个脚本不会做你想要的,但是既然这两个输入文件都不会产生NO输出,所以你必须对输入文件有所误解或者不会告诉我们。 – 2013-03-20 03:16:40

+1

'file1.txt'的目的是什么?它似乎实际上没有任何贡献。 – 2013-03-20 03:26:51

+0

file1可能具有不在file2中的字段。我想那些为空 – user1865341 2013-03-20 03:39:44

回答

4

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

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

这是通过存储键和值在file2,然后再处理文件1将它们输出。下面(略格式)记录表明这个动作:

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命令和你有:

[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 sed-i就地编辑选项)。

+0

我不知道什么是错的,我试过你的东西,我得到这个'field1 field2 field3 ' – user1865341 2013-03-20 03:25:31

+0

@ user1865341,你需要重新检查你的输入文件,以确保它们符合规范(例如,'od -xcb file2.txt')。你还需要检查你使用了一个体面的'awk'实现(例如'awk --version')。 FWIW,我正在运行'GNU Awk 3.1.7'。 – paxdiablo 2013-03-20 03:26:54

+0

我已经用我的输出更新了这个问题,你能看看什么是错的 – user1865341 2013-03-20 03:31:49

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 

(我已经张贴此作为一个评论,但它似乎并没有被可能在注释中反斜杠)

+0

如果你明白我的意思,你可以通过使用两个或多个back ticks,然后使用你想要的代码:''var ='ls'''来获得评论。在后面打勾和后面的文字之间不能有空格。 – 2013-03-20 05:03:06

+0

@JonathanLeffler阿欢呼。 – 2013-03-20 06:15:18