Linuxのファイルには、タブ区切りの大きな行列があります。
Name ID ABC12 ABCD12 ABCD123 ABCD1234
ABC12 123456 XX YY ZZ JJ
ABC12 123456 XX YY ZZ JJ
ABCD12 123456 XX YY ZZ JJ
ABCD12 123456 XX YY ZZ JJ
ABCD123 123456 XX YY ZZ JJ
ABCD123 123456 XX YY ZZ JJ
ABCD1234 123456 XX YY ZZ JJ
ABCD1234 123456 XX YY ZZ JJ
この行列を最初の列の一致に基づいて別々のファイルに分割したいと思います。 [このファイルは容量が大きく、列数をカウントできません。]
予想出力:
ファイル1;
Name ID ABC12
ABC12 123456 XX
ABC12 123456 XX
ファイル2;
Name ID ABCD12
ABCD12 123456 YY
ABCD12 123456 YY
ファイル3;
Name ID ABCD123
ABCD123 123456 ZZ
ABCD123 123456 ZZ
ファイル4;
Name ID ABCD1234
ABCD1234 123456 JJ
ABCD1234 123456 JJ
答え1
十分アッ解決策:
awk 'NR==1{ len=split($0,a_pos); for(i=1;i<=len;i++) a_keys[a_pos[i]]=i }
NR>1{ if(!r[$1]++) { fn="file"++c; print "Name\tID\t"$1 > fn }
print $1,$2,$(a_keys[$1]) > fn
}' OFS='\t' file
len=split($0,a_pos)
- 最初の行を「キー」配列(整数a_pos
でインデックス付けされた配列)に分割します。for(i=1;i<=len;i++) a_keys[a_pos[i]]=i
- 文字列キーでインデックスを付ける配列に反転a_pos
(追加処理のため)a_keys
fn="file"++c
- 構成ファイル名
結果を見る:
for f in file[0-9]*; do (echo "$f"; cat "$f"; echo); done
出力(file1
、file2
および連続file3
タイプfile4
):
file1
Name ID ABC12
ABC12 123456 XX
ABC12 123456 XX
file2
Name ID ABCD12
ABCD12 123456 YY
ABCD12 123456 YY
file3
Name ID ABCD123
ABCD123 123456 ZZ
ABCD123 123456 ZZ
file4
Name ID ABCD1234
ABCD1234 123456 JJ
ABCD1234 123456 JJ
答え2
あなたが使用できるawk
:
awk 'NR>1{if ($1!=p){N="file"++C; print "Name\tID\t"$1 >N};
print $1,$2,$(C+2)>N}{p=$1}' infile.txt
答え3
私が考える最も簡単な方法は、最初の行を変数として保存し、残りは必要に応じて印刷することです。ただし、これを行うには、入力ファイル全体をメモリに保存する必要があります。
#!/bin/gawk -f
{
if(NR==1){
header[1]=$1;
header[2]=$2;
for(i=3;i<=NF;i++){
header[$i]=i;
}
}
else{
data[$1][NR]=$2"\t"$(header[$1]);
}
}
END{
OFS="\t";
for(i in data){
print header[1],header[2],i > i".txt"
for(k in data[i]){
print i,data[i][k] >> i".txt"
}
}
}
スクリプトをfoo.awk
実行可能ファイル(chmod a+x foo.awk
)として保存し、ファイルから実行します。
foo.awk file
答え4
使用法: ./split_matrix.awk input.txt
#!/usr/bin/awk -f
BEGIN {
cnt = 1;
}
NR == 1 {
for(i = 3; i <= NF; i++) {
headers[$i] = i;
}
}
NR > 1 {
if( ! file_names[$1]) {
file_names[$1] = cnt++;
printf "%s %s %s\n", "Name", "ID", $1 > "file_"file_names[$1];
}
printf "%s %s %s\n", $1, $2, $headers[$1] >> "file_"file_names[$1];
}
テスト
入力する
Name ID ABC12 ABCD12 ABCD123 ABCD1234
ABC12 123456 XX YY ZZ JJ
ABC12 123456 XX YY ZZ JJ
ABCD12 123456 XX YY ZZ JJ
ABCD12 123456 XX YY ZZ JJ
ABCD123 123456 XX YY ZZ JJ
ABCD123 123456 XX YY ZZ JJ
ABCD1234 123456 XX YY ZZ JJ
ABCD1234 123456 XX YY ZZ JJ
出力(tail -n +1 -- file*
ファイル名とファイルの内容を印刷するためにこのトリックが見つかりました。ここ)
==> file_1 <==
Name ID ABC12
ABC12 123456 XX
ABC12 123456 XX
==> file_2 <==
Name ID ABCD12
ABCD12 123456 YY
ABCD12 123456 YY
==> file_3 <==
Name ID ABCD123
ABCD123 123456 ZZ
ABCD123 123456 ZZ
==> file_4 <==
Name ID ABCD1234
ABCD1234 123456 JJ
ABCD1234 123456 JJ