2013-03-20 63 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