
私はまだプログラミングを勉強中で、いろいろ試してみましたが、正しいフォーマットがわかりません。タブ区切り17列と多くの(約50,000)行を持つファイル。ファイルはすでに最初の列でソートされています。最初の列(A)が同じで、他の16列はすべて異なる行を結合し、すべての情報を1行に保持したいのですが、できれば同じ列にしたいです。セミコロン ;区切り文字として使用します。出力ファイルではタブを区切り文字として使用します。回答をありがとうございます。どこが間違っているのかについても説明していただけるとさらに助かります :)。
これまで試したこと:
awk -F'\t' 'NF>1{a[$1] = a[$1]";"$2}END{for(i in a){print i""a[i]}}' filename.txt
perl -F',' -anle 'next if /^$/;$h{$F[0]} = $h{$F[0]}.", ".$F[1];
END{print $_,$h{$_},"\n" for sort keys %h}' filename.txt
ファイル形式(他の15列は列Bと同じ形式です)
A B C
123 fvv ggg
123 kjf ggg
123 ccd att
567 abc gst
567 abc hgt
879 ttt tyt
必要な出力 (17 列すべてが必要で、列 2 ~ 16 については列 B と C と同じ出力が必要です)。B のすべてのケースは B の下に、C のすべてのケースは C の下に、D のすべてのケースは D の下に、というように配置する必要があります。したがって、出力には入力と同じように 17 列があり、列 1 には多くの繰り返しがあるため、50,000 行ではなく、約 20,000 行になります (この特定のファイルの場合)。
A B C
123 fvv;kjf;ccd ggg;ggg;att
567 abc;abc gst;hgt
879 ttt lll
答え1
awk '{
if(NR!=1){a[$1]=$2";"a[$1]}
else print $0}
END{
n = asorti(a, b);
for (n in b) {
print b[n],a[b[n]]
}
}'
答え2
Perl ソリューション:
$ perl -F"\t" -anle 'if($.==1){print; next} push @{$k{$F[0]}},@F[1..$#F];
END{print "$_\t" . join(";",@{$k{$_}}) for sort keys(%k)}' file
A B
123 fvv;kjf;ccd
567 abc;abc
879 ttt
これは任意の数のフィールドで機能します。ただし、かなりの数のものをメモリにロードする必要があり、ファイルが大きい場合は問題になる可能性があります。
どこで間違えたのかについては、実際に何が起こったのかを説明していただかない限りはわかりませんが、私の考えでは、Perl の試みは次の理由で失敗すると思います:
-F,
入力にタブが含まれている場合にフィールド区切り文字をコンマに設定する を使用しています。-l
と を使用していますprint "foo\n"
。 は-l
すでに各 print 呼び出しに改行を追加しているため、複数の空白行が存在することになります。- 追加するために使用している
$h{$F[0]}.", ".$F[1];
ため、初めて実行されて定義されていない場合は、保存された値の先頭に$h{$F[0]}
余分なものが追加されます。,
- 2 番目のフィールドのみを参照し、他のフィールドはすべて無視します。
同様に、次のawk
理由で失敗します:
foo""bar
各フィールド間にスペースを入れずに出力を連結して印刷します。また、タブ区切りの出力print foo,bar
も必要です。OFS="\t"
- 2 番目のフィールドのみを参照し、他のフィールドはすべて無視します。
答え3
こんな短い文章で申し訳ないのですが、こうします。
awk 'BEGIN{FS="\t"} {for(i=2; i<=NF; i++) { if (!a[$1]) a[$1]=$1FS$i ;else a[$1]=a[$1]";"$i};if ($1 != old) b[j++] = a[old];old=$1 } END{for (i=0; i<j; i++) print b[i] }' 1
123 fvv ;kjf;ccd
567 abc;abc
879 ttt
答え4
awk '
function p(n,A){
s = n
for(i=2;i<=NF;i++){
s = s "\t" A[i]
A[i] = $i
}
if(n)
print s
}
NR==1{
print
next
}
$1==n{
for(i=2;i<=NR;i++)
A[i] = A[i] ";" $i
next
}
{
p(n,A)
n = $1
}
END{
p(n,A)
}
' file