0

タブ区切りのファイルが 2 つある

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 にない場合は、空白にする必要があります。

アップデート:

これは私の端末からの出力です

    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  
4

2 に答える 2

4

考えられる解決策の1 つを次に示します。

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/]

これは、これらのフィールドがタブで区切られていないことを示しています。これは、 2 スペース シーケンスodを明確に確認できるコマンドの出力によっても確認されます。2020

それを整理する必要があります。そうしないと、コマンドが で機能しません-F"\t"。たとえば、my の各タブを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.

(または-iGNU のインプレース編集オプションを使用しますsed)。

于 2013-03-20T03:18:30.333 に答える
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

(これをコメントとして投稿したかったのですが、コメントでバッククォートをエスケープすることはできないようです)

于 2013-03-20T03:50:10.723 に答える