Awk

使用帶有 AWK 的 printf 來正確格式化我的輸出

  • April 17, 2021

我正在嘗試使用 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 ...
...

第二列應該比第一列少一個。使用我的原始文件,我基本上做了:

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 應該能夠讓我撤消科學記數法,但我無法讓它工作。

我的第一個想法是我希望第一列和第四列作為字元串,第二列和第三列作為沒有小數的浮點數字。所以,我嘗試了以下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 時,我發現了一個特點。如果我這樣做了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 

因此,第一列相對於所有其他列被下推一行,第四列被切斷。如果在您的回復中,您還可以解釋您的 printf 語法是如何工作的,我將非常感激。太感謝了!

您只是在格式字元串後缺少一個逗號,例如

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

我根本無法重現您的問題,但假設它確實存在,這可能會對您有所幫助:

$ 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

如果%dformat 不能滿足您的需要,但%4.0f可以,那麼只需更改OFMT="%d"OFMT="%4.0f".

您提到的關於第一列被下推和第四列被截斷的內容可能意味著您的輸入中有 DOS 行結尾,請參閱https://stackoverflow.com/questions/45772525/why-does-my-tool-output -覆蓋本身和如何做我修復它

引用自:https://unix.stackexchange.com/questions/645503