いくつかの出力フォーマットを指定するためにprintfとawkを使用しようとしています。デフォルトでは、最終形式は次のとおりです(すべてのタブが区切られています)。
chr10 100000624 100000625 10:100000625_A_G
chr10 100000644 100000645 10:100000645_A_C
chr10 100002463 100002464 10:100002464_C_T
chr10 100003241 100003242 10:100003242_G_T
chr10 100003303 100003304 10:100003304_A_G
chr10 10000337 10000338 10:10000338_C_T
chr10 100003515 100003516 10:100003516_A_G
chr10 100003784 100003785 10:100003785_C_T
chr10 100004359 100004360 10:100004360_A_G
chr10 100004440 100004441 10:100004441_C_G
...
起動ファイルは次のとおりです(他の列は重要ではありません)。
10:100000625_A_G G A
10:100000645_A_C C A
10:100002464_C_T C T
10:100003242_G_T G T
10:100003304_A_G G A
10:10000338_C_T T C
10:100003516_A_G A G
10:100003785_C_T C T
10:100004360_A_G A G
10:100004441_C_G C G ...
...
2番目の列は1番目の列より1列小さい必要があります。元のファイルを使用して、デフォルトで次のことを行いました。
awk -F ":" '$1=$1' OFS="\t" <(zcat <filename>) | awk -F "_" '$2=$2' OFS="\t" | awk -v OFMT="%f" 'BEGIN {OFS=FS="\t"} {print "chr"$1, $2-1, $2, $1":"$2"_"$3"_"$4}'
まず、IDの先頭を「:」に分解し、次に「_」に分解した。awk -F "[:_]"...
両方の区切り文字を使用して最初の列を分割することもできますが、最終的に違いはないと思います。
数字が科学的表記法(12000000などの数字)として報告されている場合を除いては機能しますが、これは私が望んでいません。 printfを使用すると、科学的な表記を取り消すことができるはずですが、機能することはできません。
私の最初の考えは、最初と4番目の列を文字列として、2番目と3番目の列を小数点のない浮動小数点数として欲しいということでした。だから私は次を試しましたawk '{printf "%s\t%4.0f\t%4.0f\t%s\n" "chr"$1, $2-1, $2, $1":"$2"_"$3"_"$4}'
。ただし、次のエラー メッセージが表示されます。
awk: (FILENAME=- FNR=1) fatal: not enough arguments to satisfy format string
`%s %4.0f %4.0f %s
chr10'
^ ran out for this one
フォーマット文字列が私のファイルのフィールド数と比較して長すぎるようですが、理由はわかりません。私はprintfを使って1つの機能を見つけました。これにより、awk '{printf "\t%s\t%4.0f\t%4.0f\t\n" "chr"$1, $2-1, $2, $1":"$2"_"$3"_"$4}'
次のような結果が得られます。
100000624 100000625 10
chr10 100000644 100000645 10
chr10 100002463 100002464 10
chr10 100003241 100003242 10
chr10 100003303 100003304 10
chr10 10000337 10000338 10
chr10 100003515 100003516 10
chr10 100003784 100003785 10
chr10 100004359 100004360 10
chr10 100004440 100004441 10
chr10
したがって、最初の列は他のすべての列と比較して1行下に押され、4番目の列は切り捨てられます。返信でprintf構文がどのように機能するかを説明していただきありがとうございます。とても感謝しています!
答え1
フォーマット文字列の後にカンマがありません。
awk -F'[:_\t]' '{ printf "%s\t%4.0f\t%4.0f\t%s\n", "chr"$1, $2-1, $2, $1":"$2"_"$3"_"$4 }' file
# ^
# |
# this one
答え2
問題をまったく再現することはできませんが、問題があると仮定すると役に立ちます。
$ cat tst.awk
BEGIN { OFS="\t"; OFMT="%d" }
{
split($1,f,/[:_]/)
print "chr"f[1], f[2]-1, f[2], $1
}
$ awk -f tst.awk file
chr10 100000624 100000625 10:100000625_A_G
chr10 100000644 100000645 10:100000645_A_C
chr10 100002463 100002464 10:100002464_C_T
chr10 100003241 100003242 10:100003242_G_T
chr10 100003303 100003304 10:100003304_A_G
chr10 10000337 10000338 10:10000338_C_T
chr10 100003515 100003516 10:100003516_A_G
chr10 100003784 100003785 10:100003785_C_T
chr10 100004359 100004360 10:100004360_A_G
chr10 100004440 100004441 10:100004441_C_G
%d
フォーマットが必要に応じて機能しないが、%4.0f
機能するOFMT="%d"
場合OFMT="%4.0f"
。
最初の列が下に押され、4番目の列が切り捨てられると言及されているのは、おそらく入力にDOS行の終わりがあるということです。https://stackoverflow.com/questions/45772525/why-does-my-tool-output-overwrite-itself-and-how-do-i-fix-it。
答え3
使用アッユーティリティを使用すると、次のことができます。
printf -v fmt '%s\t' '%s' '%4.0f' '%4.0f' '%s\n'
awk -F '\t' -v fmt="${fmt%?}" '
{
split($1, a, /[:_]/)
f1 = "chr" a[1]
f2 = (f3 = a[2])-1
f4 = sprintf("%4.0f", f3)
sub(/:[^_]+/, ":"f4, $1)
printf fmt, f1, f2, f3, $1
}
' file