Awk 和排序输出以逗号分隔?
Awk & Sort-Output as Comma Delimited?
我正在尝试将其输出为逗号分隔。当前版本根本不起作用(我得到一个空白文件作为输出),而以前的版本(我保留 awk BEGIN 语句但没有排序分隔符)将只输出为制表符分隔,而不是逗号分隔.在以前的版本中,在没有尝试获取逗号分隔符的情况下,我确实得到了预期的答案(使用复杂的过滤器等),所以我没有在这部分寻求帮助。我意识到这是一种非常丑陋的过滤方式,而且数字也 ugly/very 很大。
题目背景:找到文件lamina.bed中与chr12:5000000-6000000重叠的区域,按第4列降序排列,输出逗号分隔。染色体是第一列,区域的起始位置是第 2 列,结束位置是第 3 列,值是第 4 列。我们应该使用 awk(在 Unix bash shell)。预先感谢您的帮助!
awk 'BEGIN{FS="\t"; OFS=","} ( <= 5000000 && >= 5000000) || ( >= 5000000 && <= 6000000) || ( <= 6000000 && >= 6000000) || ( <= 5000000 && >= 6000000)' /vol1/opt/data/lamina.bed | awk 'BEGIN{FS=","; OFS=","} ( == "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
要获得逗号分隔的输出,请使用以下命令:
$ awk 'BEGIN{FS="\t"; OFS=","} ( <= 5000000 && >= 5000000) || ( >= 5000000 && <= 6000000) || ( <= 6000000 && >= 6000000) || ( <= 5000000 && >= 6000000) {=;print}' file | awk 'BEGIN{FS=","; OFS=","} ( == "chr12") ' | sort -t$"," -k4rn
chr12,5294045,5393088,0.923076923076923
chr12,3306736,5048326,0.913561847988077
chr12,5505370,6006665,0.791318864774624
上面唯一的变化是增加了动作:
{=;print}
awk
只会在一行中的一个或多个字段以某种方式更改时才使用新的字段分隔符重新格式化该行。 =
足以表明字段 1 已更改。因此,插入了新的字段分隔符。
此外,对 awk
的两次调用可以合并为一次调用:
awk 'BEGIN{FS="\t"; OFS=","} ( <= 5000000 && >= 5000000) || ( >= 5000000 && <= 6000000) || ( <= 6000000 && >= 6000000) || ( <= 5000000 && >= 6000000) {=; if( == "chr12") print}' file | sort -t$"," -k4rn
更简单的例子
在下文中,输入以制表符分隔,输出字段分隔符 OFS
设置为逗号。在第一个示例中,使用了 awk
命令 print
:
$ echo $'a\tb\tc' | awk -v OFS=, '{print}'
a b c
尽管 OFS=,
,输出仍保留制表符分隔符。
现在,我们添加简单语句 =
并观察输出:
$ echo $'a\tb\tc' | awk -v OFS=, '{=;print}'
a,b,c
输出现在以逗号分隔。同样,这是因为 awk
仅在认为行中的某个字段已以某种方式更改时才使用新的 OFS
重新格式化行。将 </code> 分配给自身足以触发重新格式化。</p>
<p>请注意,仅进行影响整个行的更改是不够的。例如,以下不会触发重新格式化:</p>
<pre><code>$ echo $'a\tb\tc' | awk -v OFS=, '{[=15=]=[=15=];print}'
a b c
需要单独更改该行的一个或多个字段。在下文中,sub
作为一个整体对 [=30=]
进行操作,因此不会触发重新格式化:
$ echo $'a\tb\tc' | awk -v OFS=, '{sub(,"NEW");print}'
NEW b c
但是,在下面的示例中,sub
专门针对字段 </code> 进行操作,因此会触发重新格式化:</p>
<pre><code>$ echo $'a\tb\tc' | awk -v OFS=, '{sub(,"NEW", );print}'
NEW,b,c
我正在尝试将其输出为逗号分隔。当前版本根本不起作用(我得到一个空白文件作为输出),而以前的版本(我保留 awk BEGIN 语句但没有排序分隔符)将只输出为制表符分隔,而不是逗号分隔.在以前的版本中,在没有尝试获取逗号分隔符的情况下,我确实得到了预期的答案(使用复杂的过滤器等),所以我没有在这部分寻求帮助。我意识到这是一种非常丑陋的过滤方式,而且数字也 ugly/very 很大。
题目背景:找到文件lamina.bed中与chr12:5000000-6000000重叠的区域,按第4列降序排列,输出逗号分隔。染色体是第一列,区域的起始位置是第 2 列,结束位置是第 3 列,值是第 4 列。我们应该使用 awk(在 Unix bash shell)。预先感谢您的帮助!
awk 'BEGIN{FS="\t"; OFS=","} ( <= 5000000 && >= 5000000) || ( >= 5000000 && <= 6000000) || ( <= 6000000 && >= 6000000) || ( <= 5000000 && >= 6000000)' /vol1/opt/data/lamina.bed | awk 'BEGIN{FS=","; OFS=","} ( == "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
要获得逗号分隔的输出,请使用以下命令:
$ awk 'BEGIN{FS="\t"; OFS=","} ( <= 5000000 && >= 5000000) || ( >= 5000000 && <= 6000000) || ( <= 6000000 && >= 6000000) || ( <= 5000000 && >= 6000000) {=;print}' file | awk 'BEGIN{FS=","; OFS=","} ( == "chr12") ' | sort -t$"," -k4rn
chr12,5294045,5393088,0.923076923076923
chr12,3306736,5048326,0.913561847988077
chr12,5505370,6006665,0.791318864774624
上面唯一的变化是增加了动作:
{=;print}
awk
只会在一行中的一个或多个字段以某种方式更改时才使用新的字段分隔符重新格式化该行。 =
足以表明字段 1 已更改。因此,插入了新的字段分隔符。
此外,对 awk
的两次调用可以合并为一次调用:
awk 'BEGIN{FS="\t"; OFS=","} ( <= 5000000 && >= 5000000) || ( >= 5000000 && <= 6000000) || ( <= 6000000 && >= 6000000) || ( <= 5000000 && >= 6000000) {=; if( == "chr12") print}' file | sort -t$"," -k4rn
更简单的例子
在下文中,输入以制表符分隔,输出字段分隔符 OFS
设置为逗号。在第一个示例中,使用了 awk
命令 print
:
$ echo $'a\tb\tc' | awk -v OFS=, '{print}'
a b c
尽管 OFS=,
,输出仍保留制表符分隔符。
现在,我们添加简单语句 =
并观察输出:
$ echo $'a\tb\tc' | awk -v OFS=, '{=;print}'
a,b,c
输出现在以逗号分隔。同样,这是因为 awk
仅在认为行中的某个字段已以某种方式更改时才使用新的 OFS
重新格式化行。将 </code> 分配给自身足以触发重新格式化。</p>
<p>请注意,仅进行影响整个行的更改是不够的。例如,以下不会触发重新格式化:</p>
<pre><code>$ echo $'a\tb\tc' | awk -v OFS=, '{[=15=]=[=15=];print}'
a b c
需要单独更改该行的一个或多个字段。在下文中,sub
作为一个整体对 [=30=]
进行操作,因此不会触发重新格式化:
$ echo $'a\tb\tc' | awk -v OFS=, '{sub(,"NEW");print}'
NEW b c
但是,在下面的示例中,sub
专门针对字段 </code> 进行操作,因此会触发重新格式化:</p>
<pre><code>$ echo $'a\tb\tc' | awk -v OFS=, '{sub(,"NEW", );print}'
NEW,b,c