2016-07-21 12 views
-1

で複数のファイルを結合する私は、次のファイル(アンダースコアはファイルの内容に含まれていないファイル名、タブ区切り文字を表す)を持つ:Linuxの

(sample001.file)

Name_____scores_____gender 
Joey_____54_____Boy 
Kyle_____87_____Girl 
Sia______43_____Girl 
Marge____87_____Girl 

(sample002.file)

Name_____scores_____gender 
Joey_____23_____Boy 
Pedro____76_____Boy 
Kyle_____76_____Girl 

(sample003.file)

Name_____scores_____gender 
Kyle_____34_____Girl 
James____65_____Boy 
Pedro____76_____Boy 
Sia______65_____Girl 
Marge____23_____Girl 

これらのファイルをすべて1つに統合したいと思います.1番目と2番目の列のデータだけが含まれています。それは次のようになります。

(integrate.file)

Name_____sample001____sample002_____sample003 
Joey_____54_____23____0 
Kyle_____87_____76____34 
Sia______43_____0_____65 
Marge____87_____0_____23 
Pedro____0______76____76 
James____0______0_____65 

基本的には、名前だけで最初の列の単一のエントリを持つ必要があり、かつ任意のサンプルのデータが存在しない場合は、それがあるべきことゼロ。ヘッダーは必要ではありませんが、存在する可能性があります。

誰もが私にこれを助けることができますか?バッシュとprocess substitutionを使用して

+0

あなたが試したコマンドを投稿してください – Sundeep

+0

[ディレクトリ内のすべてのファイルを結合](http://stackoverflow.com/questions/3903868)と[可変番号の列を結合する最も簡単な方法は何ですか?のファイル?](http://stackoverflow.com/questions/18466662)。 –

答えて

1

、あなたは(かなり長い)単一コマンドパイプラインに三つのファイルのためにそれにそれを行うことができます。joinは、結合列、上でソートされてその入力を必要とすることが

join -e 0 -a 1 -a 2 -t $'\t' -o 0,1.2,2.2 \ 
    <(sed 1d sample001.file | sort) \ 
    <(sed 1d sample002.file | sort) | 
join -e 0 -a 1 -a 2 -t $'\t' -o 0,1.2,1.3,2.2 \ 
    - <(sed 1d sample003.file | sort) 

注意この場合、列1。 sed 1dコマンドは、データをソートする前に見出し行を削除します。

-e0には、値がない場合は「0を入力してください」と表示されます。 -a1-a2のオプションでは、 'ファイル1とファイル2のすべての行を保持する'というオプションがあります。 -t $'\t'オプションは、BashのANSI C Quotingを使用してセパレータのタブを生成します。 -tオプションを省略した場合は '動作します'が、出力列はタブではなく空白で区切られます。 -oオプションは、印刷する列を指定します。0は結合列(各ファイルの列1)です。 1.2は、ファイル1の列2などです。は、2番目のjoinのファイル名は「標準入力の読み取り」を意味します。

サンプルデータ上のものからの出力は次のとおりです。

James 0  0  65 
Joey 54  23  0 
Kyle 87  76  34 
Marge 87  0  23 
Pedro 0  76  76 
Sia  43  0  65 

はここ10個のサンプルファイルを扱ういくつかのコードです。私もデータを生成するために必要なので、私はそれを行うには、私のツールキットからツールの数を使用 - randomperturbrange(標準seqに非常によく似ています)とshuffle:ランダムで

for sample in $(range -f '%03d' 1 10) 
do 
    random -n 9 -T '%{ABCDEFJKMPS}s %[11:90]d %{BG}s' | 
    sort -u -k1,1 | 
    join -o 1.2,2.2,2.3 names - | 
    shuffle | 
    sed 's// /g' | 
    perturb -f '%2.0f' -p 10 -c 2 > "sample$sample.file" 
done 

一つの小さな問題データジェネレータはまだ(マルチキャラクタ)の名前のリストからランダムなエントリを選択することを許可していないので、イニシャルのリストを使用してnamesファイルで名前にマップしました。それはちょっと変だけど、あなたのデータはすでに持っていて、ランダムなデータを生成する必要はありません。 ファイルnames含まれている:例えば

A Alex 
B Belle 
C Cynthia 
D Doreen 
E Elizabeth 
F Ferdinand 
J James 
J Joey 
K Kyle 
M Marge 
P Pedro 
S Sia 

を、sample001.fileを含む終わった:

Belle 81  B 
Marge 62  B 
Ferdinand  37  B 
Sia  44  B 
Doreen 45  G 
Elizabeth  18  G 
Joey 16  B 
James 19  B 

その後、参加コードが任意の加入を行う前に、すべての名前のリストを生成する必要があり、そうでないあなたがいません最初のサンプルファイルに表示されない名前の適切なスコアを参照してください。これは非標準のツールを使用しません。

tmp=$(mktemp ./tmp.XXXXXX) 
trap 'rm -f "$tmp" "$tmp".?; exit 1' 0 1 2 3 13 15 

sed 's/[[:space:]].*//' "[email protected]" | sort -u > $tmp.0 

join_cmd() 
{ 
    join -e 0 -a 1 -a 2 -o "$outcols" "[email protected]" > "$tmp.2" 
} 

outcols="0,2.2" 
# Generate list of all names 
join_cmd "$tmp.0" <(sort "$1") 
mv "$tmp.2" "$tmp.1" 
shift 
outcols="0,1.2,2.2" 

for sample in "[email protected]" 
do 
    join_cmd "$tmp.1" <(sort "$sample") 
    sed 's/[[:space:]]\([0-9][0-9]*\)$/,\1/' "$tmp.2" > "$tmp.1" 
done 

# Don't hard code the output file name — do that on the command line that 
# invokes this script (same as you specify the input file names on the command line). 
sed 's/,/ /g' "$tmp.1" # > integrate.file 

rm -f "$tmp" "$tmp".? 
trap 0 1 2 3 13 15 

これは、カンマで区切られたリストに番号をマッピングすることによって、結合列のリストを継続的に拡張する必要なく、なくなります。

$ column -t integrate.file 
Alex  0 0 78 0 65 21 0 38 64 0 
Belle  81 12 15 58 0 27 0 13 0 52 
Cynthia 0 58 0 52 12 0 0 77 0 94 
Doreen  45 49 0 85 0 0 57 32 81 63 
Elizabeth 18 64 19 39 18 94 52 0 0 25 
Ferdinand 37 0 0 0 0 64 72 21 0 28 
James  19 0 0 77 0 48 78 59 39 23 
Joey  16 0 0 79 0 48 78 70 39 19 
Kyle  0 80 0 65 54 26 0 88 0 0 
Marge  62 37 13 0 0 81 0 0 24 69 
Pedro  0 0 40 0 47 74 79 0 0 0 
Sia  44 0 27 0 55 0 43 0 32 0 
$ 

sample000.fileの内容は、出力の2列目に表示されます。出力にはnamesのすべての名前が表示され、各サンプルファイルには番号があることがわかります。

+0

ありがとうございます。しかし、私は多くのファイルをマージしようとしています。どうすればこのことができますか? –

+0

[comment](http://stackoverflow.com/questions/38494701/joining-multiple-files-in-linux/38495499?noredirect=1#comment64390999_38494701)を参照してください。質問には、複数の質問ファイル。基本的な手法は2つのファイルを結合して新しいファイルを作成することです。新しいファイルと別のオリジナルを結合してさらに別のファイルを作成し、すべてのファイルが処理されるまで繰り返します。もう1つのオプションは、この答えに示されているものに類似したシェルスクリプトを生成し、余分なデータファイルごとに新しい 'join'を追加することです。 –

+0

番号間の空白や名前と最初の番号の間のタブのみを使用して、結合処理を簡素化できるかどうかを考えたいと思うかもしれません。これにより、各コマンドセットに同じ結合リストを持つことができます。あるいは、PerlやPythonに移行することもできます。 –