最初の列に基づいて複数のファイルを1つのファイルに貼り付けます。

最初の列に基づいて複数のファイルを1つのファイルに貼り付けます。

ファイルが複数あり、各ファイルの最初の列に基づいてマージする必要があります。

ファイル1:

foo  12  
jhdfeg 25  
kjfdgkl 37

ファイル2:

foo 23  
jhdfeg 45

ファイル3:

foo 35  
djhf 37  

出力は次のようにする必要があります

        file1 file2  file3  
foo     12    23     35  
jhdfeg  25    45     0  
kjfdgkl 37    0      0  
djhf    0     0      37

答え1

アッ方法:

joiner.awkスクリプト:

#!/bin/awk -f
BEGIN { 
    f1=ARGV[1]; f2=ARGV[2]; f3=ARGV[3]     # the 1st, 2nd and 3rd file names respectively
    printf("%10s\t%s\t%s\t%s\n", "", f1, f2, f3)   # printing header
}
{ a[$1][FILENAME]=$2 }    # accumulating values
END {
    for (i in a) {
        printf("%-10s\t%d\t%d\t%d\n", i, a[i][f1], a[i][f2], a[i][f3]) 
    }
}

使用法:

awk -f joiner.awk file1 file2 file3

出力:

          file1 fil2 file3
kjfdgkl     37  0   0
foo         12  23  35
djhf        0   0   37
jhdfeg      25  45  0

答え2

perl -F'\s+' -lane '

   $. == 1 and @ARGC = ($ARGV, @ARGV);       # initialize the @ARGC array

   exists $h{$F[0]} or $h[keys %h] = $F[0];  # needed to remember order

   $h{$F[0]}->[@ARGC-@ARGV-1] = $F[1];       # populate hash

   END {
      $, = "\t";           # set the OFS to TAB

      print q//, @ARGC;    # print the first line with filenames

      for my $key (@h) {   # print remaninig lines with data
         print $key,
            map { $h{$key}->[$_] // 0 } 0 .. $#ARGC;
      }
   }

' file1 file2 file3 # ... you can give as many files here

出力

        file1   file2   file3
foo     12      23      35
jhdfeg  25      45      0
kjfdgkl 37      0       0
djhf    0       0       37

答え3

あなたの例のように3つのファイルがある場合は、 join魔法を使ってこれを行うことができます。まず、タブ区切りのファイル名を出力ファイルに書き込みます。

for i in File*; do printf "\t%s" "$i" >> RES; done

実際の結果に空白行を追加します。

printf '\n' >> RES

joinonを使用しFile1File2出力を一時ファイルにリダイレクトします。

join  -a1 -a2  -e0 <(sort File1) -o 0 1.2 2.2 <(sort File2) > TEMP_FILE

ここで上記のコマンドの出力を再度使用してくださいFile3(ここではパイプ()を使用することもできます|)。

join  -a1 -a2  -e0 <(sort TEMP_FILE) -o 0 1.2 1.3 2.2 <(sort File3) >> RES

スペースをタブに置き換えますRES

tr ' ' '\t' < RES > FINAL_RES

結果は次の場所にありますFINAL_RES

$ cat FINAL_RES
        File1   File2   File3
foo     12      23      35
jhdfeg  25      45      0
kjfdgkl 37      0       0

答え4

ファイル数に関係なく、より一般的なアプローチは次のとおりですsed

sed '1{x;s/$/_/;x;}
  /foo/{x;s/_/ 0_/g;x;}
  G;s/^\([a-z]*\)  *\([0-9]*\).*\n\(.*_\)\1\([^_]*\)0/\3\1\4\2/
  s/^\([a-z]*\) *\([0-9]*\).*\n\([^_]*\)0_\(.*\)/\30_\4\1\3\2_/
  $! {h;d;}
  s/[^_]*_//
  y/_/\n/' file*

これはfoo、例に示すように、その行で始まるすべてのファイルに依存します。

sedこれで、仕組み、パターン空間、スペースの維持に関する基本がわかったので、説明は次のとおりです。

主なアイデアは、予約されたスペースに完全な出力テーブルを構築することです。各行に予約されているスペースには、そのポイントのテーブルと新しい行に必要なテンプレート行が含まれます。_処理中に行区切り文字として使用します。今段階的に:

1{x;s/$/_/;x;}

これにより、_テンプレート行の先頭に単一を使用して予約済みスペースが初期化されます。

/foo/{x;s/_/ 0_/g;x;}

/foo/foo新しいファイルの開始を示すインクルード行を指定します。この場合、次のコマンドが実行されます{}。予約済みスペースのすべての行(実際のテーブル行とテンプレート行)が0追加されます。後でその行のキーワードを検出すると、0正しい数字に置き換えられます。キーワードが表示されない場合は保持0されます。

G;s/^\([a-z]*\) *\([0-9]*\).*\n\(.*_\)\1\([^_]*\)0/\3\1\4\2/

「G」は、予約済みスペースをパターンスペースに追加します。コマンドsは4つの部分で構成されています。最初の部分にはキーワードが含まれ、2番目の部分には値が含まれ、3番目の部分にはキーワードが2番目に表示されるまで(逆参照)、\(\)改行文字の後のすべての項目が含まれます(したがって、これは予約済みスペースに追加されます)されたテーブルです)。\1。 4番目の項目は、最後の項目を除く行のすべての項目を所有します0。したがって、そのキーワードを含む既存の行を見つけ、0すべてを改行文字に入れ、更新されたテーブルを保持します。

s/^\([a-z]*\) *\([0-9]*\).*\n\([^_]*\)0_\(.*\)/\30_\4\1\3\2_/

別の一致には newline が含まれているため、\nテーブルでキーワードが見つからなかったことがわかります(そうでなければ、前の行から改行が削除された可能性があります。したがって、今回はキーワードで構成された新しい行を最後に追加します。テンプレート行の秘密です。0新しいファイルごとに列を追加するため、列を削除すると、0各ファイルにキーワードのない列が1つずつあります。0

$! {h;d;}

最後の行でない場合は、変更されたテーブルを再予約済みスペース(h)に移動して再起動します(d)。

s/[^_]*_//

最後の行の場合、テンプレート行は削除されます。

y/_/\n/

_これは改行文字を置き換えます。また、必要に応じてスペースをタブに置き換えることもできます。

編集する

すべてのファイルがその行で始まるという仮定が間違っている場合は、各ファイルの先頭に追加の行を追加してコンテンツ全体を次にストリーミングするなど、新しいファイルが開始されるタイミングを知るための別のfoo方法が必要です。sedsed

for file in file*; do
  echo Start of $file
  cat $file
done | sed '1{x;s/$/__/;x;}
  /Start of/{G;s/_/ 0_/g;s/Start of \(.*\)\n\([^_]*\)_\([^_]*\) 0/\2_\3 \1/;x;d;}
  G;l;s/^\([a-z]*\)  *\([0-9]*\).*\n\(.*_\)\1\([^_]*\)0/\3\1\4\2/
  l;s/^\([a-z]*\) *\([0-9]*\).*\n\([^_]*\)0_\(.*\)/\3 0_\4\1\3\2_/
  $! {h;d;}
  s/[^_]*_//
  y/_/\n/'

このバージョンでは、すべてのファイル名を列ヘッダーとして使用して、テーブルのヘッダー行も生成します。

関連情報