我有一个制表符分隔的文件,如下所示:
cg13201342 F ARNT;ARNT;ARNT;CTSK 3'UTR;3'UTR;3'UTR;TSS1500
cg05269359 F SCN4B;SCN4B;SCN4B;SCN4B 3'UTR;3'UTR;3'UTR;Body
cg06018296 R NEK3;NEK3;NEK3;NEK3 3'UTR;3'UTR;3'UTR;Body
cg05172994 F WDR20;WDR20;WDR20;WDR20 3'UTR;3'UTR;3'UTR;Body
期望的输出:
cg13201342 F ARNT 3'UTR
cg13201342 F ARNT 3'UTR
cg13201342 F ARNT 3'UTR
cg13201342 F CTSK TSS1500
cg05269359 F SCN4B 3'UTR
.
.
等等
我试过
awk 'BEGIN {
FS = OFS = "\t"
}
{
n = split($3, f, " *;*")
for (i=1; i<=n; i++)
print $1, f[i]
}' probe-genes-regions >chk
但这只是分割第三列。我希望最后一列与第二列分开,并分别与第三列的第一个字段和最后一列的第一个字段形成行,依此类推
答案1
将字段 3 和 4 用分号拆分为单独的数组,然后对它们进行迭代,例如(假设字段 3 和 4 具有相同数量的元素):
解析.awk
BEGIN { OFS = "\t" }
{
n = split($3, a, /;/); split($4, b, /;/)
for(i=1; i<=n; i++)
print $1, $2, a[i], b[i]
}
像这样运行它:
awk -f parse.awk infile
输出:
cg13201342 F ARNT 3'UTR
cg13201342 F ARNT 3'UTR
cg13201342 F ARNT 3'UTR
cg13201342 F CTSK TSS1500
cg05269359 F SCN4B 3'UTR
cg05269359 F SCN4B 3'UTR
cg05269359 F SCN4B 3'UTR
cg05269359 F SCN4B Body
cg06018296 R NEK3 3'UTR
cg06018296 R NEK3 3'UTR
cg06018296 R NEK3 3'UTR
cg06018296 R NEK3 Body
cg05172994 F WDR20 3'UTR
cg05172994 F WDR20 3'UTR
cg05172994 F WDR20 3'UTR
cg05172994 F WDR20 Body
答案2
使用磨坊主( mlr
):
sed 's/;/\t/' file | mlr --nidx --fs tab nest --evar ';' -f 4
首先使用制表sed
符替换;
每行的第一行,将第三个制表符分隔字段分成两个单独的字段。 GNU可以使用该命令sed
插入制表符,但并非所有实现都可以。如果您不能,请输入文字制表符来代替按+ 。\t
s
sed
\t
Ctrl+VTab
然后,Miller 读取和写入制表符分隔数据 ( ),并根据第四个制表符分隔字段 ( ) 的分隔子字段--nidx --fs tab
“分解”(或“取消嵌套”)每条记录。;
nest --evar ';' -f 4
给出问题中的数据的输出:
cg13201342 F ARNT ARNT
cg13201342 F ARNT ARNT
cg13201342 F ARNT CTSK 3'UTR
cg13201342 F ARNT 3'UTR
cg13201342 F ARNT 3'UTR
cg13201342 F ARNT TSS1500
cg05269359 F SCN4B SCN4B
cg05269359 F SCN4B SCN4B
cg05269359 F SCN4B SCN4B 3'UTR
cg05269359 F SCN4B 3'UTR
cg05269359 F SCN4B 3'UTR
cg05269359 F SCN4B Body
cg06018296 R NEK3 NEK3
cg06018296 R NEK3 NEK3
cg06018296 R NEK3 NEK3 3'UTR
cg06018296 R NEK3 3'UTR
cg06018296 R NEK3 3'UTR
cg06018296 R NEK3 Body
cg05172994 F WDR20 WDR20
cg05172994 F WDR20 WDR20
cg05172994 F WDR20 WDR20 3'UTR
cg05172994 F WDR20 3'UTR
cg05172994 F WDR20 3'UTR
cg05172994 F WDR20 Body
通过此操作uniq
将删除相邻行的重复项。
仅使用awk
:
awk -F '\t' 'BEGIN { OFS=FS }
{
nf = split($3,a,";")
for (i = 2; i <= nf; ++i) print $1, $2, a[1], a[i]
}' file
这将第三场分割;
,然后对于第三场的第二子场,继续输出前两个场以及原始第三场的第一个子场。
其输出与该答案顶部的管道的输出相同。
答案3
使用任何 POSIX awk,无论输入中的空格是什么:
$ awk -F'[[:space:];]+' -v OFS='\t' '{
n=(NF-2)/2; for (i=1; i<=n; i++) print $1, $2, $(2+i), $(2+i+n)
}' file
cg13201342 F ARNT 3'UTR
cg13201342 F ARNT 3'UTR
cg13201342 F ARNT 3'UTR
cg13201342 F CTSK TSS1500
cg05269359 F SCN4B 3'UTR
cg05269359 F SCN4B 3'UTR
cg05269359 F SCN4B 3'UTR
cg05269359 F SCN4B Body
cg06018296 R NEK3 3'UTR
cg06018296 R NEK3 3'UTR
cg06018296 R NEK3 3'UTR
cg06018296 R NEK3 Body
cg05172994 F WDR20 3'UTR
cg05172994 F WDR20 3'UTR
cg05172994 F WDR20 3'UTR
cg05172994 F WDR20 Body