Awk& Sort-Output为逗号分隔?

时间:2015-02-08 23:10:00

标签: bash shell awk comma delimited

我试图以逗号分隔输出。当前版本根本不起作用(我得到一个空白文件作为输出),以前的版本(我保留awk BEGIN语句,但没有排序分隔符)将只输出制表符分隔,而不是逗号分隔。在以前的版本中,没有尝试获取逗号分隔符,我确实得到了预期的答案(使用复杂的过滤器等),所以我不是要求帮助它的那一部分。我意识到这是一种非常丑陋的过滤方式,数字也很丑/非常大。

问题的背景:找到文件lamina.bed中与chr12区域重叠的区域:5000000-6000000,并按列4降序排序,输出为逗号分隔。染色体是第一列,区域的起始位置是第2列,结束位置是第3列,值是第4列。我们应该使用awk(在Unix bash shell中)。提前感谢您的帮助!

awk 'BEGIN{FS="\t"; OFS=","} ($2 <= 5000000 && $3 >= 5000000) || ($2 >= 5000000 && $3 <= 6000000) || ($2 <= 6000000 && $3 >= 6000000) || ($2 <= 5000000 && $3 >= 6000000)' /vol1/opt/data/lamina.bed | awk 'BEGIN{FS=","; OFS=","} ($1 == "chr12") ' | sort -t$"," -k4rn > ~/MOLB7621/PS_2/results/2015_02_05/PS2_p3_n1.csv
cat ~/MOLB7621/PS_2/results/2015_02_05/PS2_p3_n1.csv

输入的样本行(制表符分隔,包括chr12上应该起作用的行):

#chrom  start   end value
chr1    11323785    11617177    0.86217008797654
chr1    12645605    13926923    0.934891485809683
chr1    14750216    15119039    0.945945945945946
chr12   3306736 5048326 0.913561847988077
chr12   5294045 5393088 0.923076923076923
chr12   5505370 6006665 0.791318864774624
chr12   7214638 7827375 0.8562874251497
chr12   8139885 10173149    0.884353741496599

1 个答案:

答案 0 :(得分:2)

要获得以逗号分隔的输出,请使用以下命令:

$ awk 'BEGIN{FS="\t"; OFS=","} ($2 <= 5000000 && $3 >= 5000000) || ($2 >= 5000000 && $3 <= 6000000) || ($2 <= 6000000 && $3 >= 6000000) || ($2 <= 5000000 && $3 >= 6000000) {$1=$1;print}' file | awk 'BEGIN{FS=","; OFS=","} ($1 == "chr12") ' | sort -t$"," -k4rn 
chr12,5294045,5393088,0.923076923076923
chr12,3306736,5048326,0.913561847988077
chr12,5505370,6006665,0.791318864774624

上面唯一的变化是对行动的补充:

{$1=$1;print}
如果线路上的一个或多个字段以某种方式更改,

awk将仅重新格式化具有新字段分隔符的行。 $1=$1足以表示字段1已更改。因此,插入了新的字段分隔符。

此外,对awk的两次调用可以合并为一个调用:

awk 'BEGIN{FS="\t"; OFS=","} ($2 <= 5000000 && $3 >= 5000000) || ($2 >= 5000000 && $3 <= 6000000) || ($2 <= 6000000 && $3 >= 6000000) || ($2 <= 5000000 && $3 >= 6000000) {$1=$1; if($1 == "chr12") print}' file | sort -t$"," -k4rn

更简单的例子

在下文中,输入以制表符分隔,输出字段分隔符OFS设置为逗号。在第一个示例中,使用了awk命令print

$ echo $'a\tb\tc' | awk -v OFS=, '{print}'
a       b       c

尽管OFS=,,但输出仍保留制表符分隔符。

现在,我们添加简单语句$1=$1并观察输出:

$ echo $'a\tb\tc' | awk -v OFS=, '{$1=$1;print}'
a,b,c

输出现在以逗号分隔。同样,这是因为awk只有在认为线上的字段以某种方式发生了变化时,才会使用新的OFS重新格式化一行。将$1分配给自身足以触发重新格式化。

请注意,进行影响整个行的更改是不够的。例如,以下内容不会触发重新格式化:

$ echo $'a\tb\tc' | awk -v OFS=, '{$0=$0;print}'
a       b       c

必须单独更改该行的一个或多个字段。在下文中,sub作为一个整体在$0上运行,因此不会触发重新格式化:

$ echo $'a\tb\tc' | awk -v OFS=, '{sub($1,"NEW");print}'
NEW     b       c

但是,在下面的示例中,sub专门针对字段$1进行操作,因此会触发重新格式化:

$ echo $'a\tb\tc' | awk -v OFS=, '{sub($1,"NEW", $1);print}'
NEW,b,c