0

我想对两个带有 id 和一些相应数值的文件进行简单的解析。我不想让 awk 以科学计数法打印数字。

文件如下所示:

someid-1 860025 50.0401 4.00022
someid-2 384319 22.3614 1.78758
someid-3 52096 3.03118 0.242314
someid-4 43770 2.54674 0.203587
someid-5 33747 1.96355 0.156967
someid-6 20281 1.18004 0.0943328
someid-7 12231 0.711655 0.0568899
someid-8 10936 0.636306 0.0508665
someid-9 10224.8 0.594925 0.0475585
someid-10 10188.8 0.59283 0.047391

当使用 print 而不是 printf 时:

awk 'BEGIN{FS=OFS="\t"} NR==FNR{x[$1]=$0;next} ($1 in x){split(x[$1],k,FS); print $1,k[2],k[3],k[4],$2,$3,$4}' OSCAo.txt dme_miRNA_PIWI_OSC.txt | sort -n -r -k 7 | head

我得到这个结果:

dme-miR-iab-4-5p      0.333333    0.000016    0.000001  0.25    0.000605606 9.36543e-07
dme-miR-9c-5p   10987.300000      0.525413    0.048798  160.2   0.388072    0.000600137
dme-miR-9c-3p   731.986000    0.035003    0.003251  2.10714 0.00510439  7.89372e-06
dme-miR-9b-5p   30322.500000      1.450020    0.134670  595.067 1.4415  0.00222922
dme-miR-9b-3p   2628.280000   0.125684    0.011673  48  0.116276    0.000179816
dme-miR-9a-3p    10.365000    0.000496    0.000046  0.25    0.000605606 9.36543e-07
dme-miR-999-5p  103.433000    0.004946    0.000459  0.0769231   0.00018634  2.88167e-07
dme-miR-999-3p  1513.790000   0.072389    0.006723  28  0.0678278   0.000104893
dme-miR-998-5p  514.000000    0.024579    0.002283  73  0.176837    0.000273471
dme-miR-998-3p  3529.000000   0.168756    0.015673  42  0.101742    0.000157339

注意最后一栏的科学记数法

我知道带有适当格式修饰符的 printf 可以完成这项工作,但代码变得非常冗长。我必须写这样的东西:

awk 'BEGIN{FS=OFS="\t"} NR==FNR{x[$1]=$0;next} ($1 in x){split(x[$1],k,FS); printf "%s\t%3.6f\t%3.6f\t%3.6f\t%3.6f\t%3.6f\t%3.6f\n", $1,k[2],k[3],k[4],$2,$3,$4}' file1.txt file2.txt > fileout.txt

当我必须fileout使用另一个类似结构的文件进行解析时,这变得很笨拙。

有没有办法指定默认的数字输出,这样任何字符串都将像字符串一样打印,但所有数字都遵循特定的格式。

4

2 回答 2

3

我认为你误解了%3.6f. 小数点前的第一个数字是字段宽度,而不是“小数点前的位数”。(见打印(3)

所以你应该%10.6f改用。它可以很容易地在bash

$ printf "%3.6f\n%3.6f\n%3.6f" 123.456 12.345 1.234
123.456000
12.345000
1.234000
$ printf "%10.6f\n%10.6f\n%10.6f" 123.456 12.345 1.234
123.456000
 12.345000
  1.234000

您可以看到后者正确对齐小数点。

如前所述sidharth c nadhan,您可以使用OFMT awk内部变量(似乎awk(1))。一个例子:

$ awk 'BEGIN{print 123.456; print 12.345; print 1.234}'
123.456
12.345
1.234
$ awk -vOFMT=%10.6f 'BEGIN{print 123.456; print 12.345; print 1.234}'
123.456000
 12.345000
  1.234000

正如我在您的示例中看到的,最大位数的数字可以是 123456.1234567,因此格式%15.7f涵盖所有内容并显示漂亮的表格。

但不幸的是,如果数字中没有小数点,或者即使有,它也不会起作用,但它以 . 结尾.0

$ awk -vOFMT=%15.7f 'BEGIN{print 123.456;print 123;print 123.0;print 0.0+123.0}'
    123.4560000
123
123
123

我什至尝试过gawk'sstrtonum()函数,但整数被视为非 OFMT 字符串。看

awk -vOFMT=%15.7f -vCONVFMT=%15.7f 'BEGIN{print 123.456; print strtonum(123); print strtonum(123.0)}'

它具有与以前相同的输出。

所以我认为,printf无论如何你都必须使用。该脚本可以更短一些并且更易于配置:

awk -vf='\t'%15.7f 'NR==FNR{x[$1]=sprintf("%s"f f f,$1,$2,$3,$4);next}$1 in x{printf("%s"f f f"\n",x[$1],$2,$3,$4)}' file1.txt file2.txt

如果第一个文件中有重复的 ID,该脚本将无法正常工作。如果没有发生,则可以更改这两个条件,并且;next可以将其保留。

于 2013-04-24T08:04:52.077 回答
0
awk 'NR==FNR{x[$1]=$0;next} ($1 in x){split(x[$1],k,FS); printf "%s\t%9s\t%9s\t%9s\t%9s\t%9s\t%9s\n", $1,k[2],k[3],k[4],$2,$3,$4}' file1.txt file2.txt > fileout.txt
于 2013-04-24T06:55:11.393 回答