我有这个数据选项卡分隔:
ed00011 89 0.12 NA NA No
ed0002s 28 0.11 c3(3.1e-1) NA No
ed0001 22 0.37 NA 186_CR_NCR8_Ot(1.5e-6) No
ed0002a 596 0.89 c301(9.5e-2) 17_CY7_Ot(0.03) Yes
我想根据“(...)”(如果存在)拆分第 4 列和第 5 列。如果不存在,则仅具有 NA。例如:
ed00011 89 0.12 NA NA NA NA No
ed0002s 28 0.11 c3 3.1e-1 NA NA No
ed0001 22 0.37 NA NA 186_CR_NCR8_Ot 1.5e-6 No
ed0002a 596 0.89 c301 9.5e-2 17_CY7_Ot 0.03 Yes
我尝试使用此处建议的命令:使用 awk 分割列 但是,当我没有“(...)”时,我的列就会混乱。有什么建议么?
答案1
awk 'BEGIN { OFS="\t"; }
{
if (match($4, /\(.*\)/) > 0) {
$4=substr($4, 1, RSTART - 1)"\t"substr($4, RSTART + 1, RLENGTH - 2)
} else {
$4=$4"\tNA"
}
if (match($5, /\(.*\)/) > 0) {
$5=substr($5, 1, RSTART - 1)"\t"substr($5, RSTART + 1, RLENGTH - 2)
} else {
$5=$5"\tNA"
}
print
}' input > output
这里的基本结构是在每一行检查字段 4 或字段 5 是否包含一对匹配的括号。如果是这样,则将该字段替换为两个制表符分隔的值:括号之前的部分和括号内的部分。 RSTART 值是左括号所在的位置,RLENGTH 值包括右括号,因此您会看到一些长度调整。如果这些字段不包含括号,则会附加制表符和“NA”。
重新计算列后,将打印新行。
答案2
BEGIN {
OFS = FS = "\t"
}
{
# Shift some fields to the right to make space for new fields after
# field 4 and 5.
$8 = $6
$6 = $5
# Try matching "(...)" in $4
if (match($4, "[(][^)]+[)]")) {
# Succeeded, make $5 the bit inside the parenthesis
$5 = substr($4, RSTART+1, RLENGTH-2)
# ... and $4 the bit before the parenthesis.
$4 = substr($4, 1, RSTART-1)
} else
$5 = "NA"
# Repeat for $6
if (match($6, "[(][^)]+[)]")) {
$7 = substr($6, RSTART+1, RLENGTH-2)
$6 = substr($6, 1, RSTART-1)
} else
$7 = "NA"
print
}
测试:
$ awk -f script.awk file
ed00011 89 0.12 NA NA NA NA No
ed0002s 28 0.11 c3 3.1e-1 NA NA No
ed0001 22 0.37 NA NA 186_CR_NCR8_Ot 1.5e-6 No
ed0002a 596 0.89 c301 9.5e-2 17_CY7_Ot 0.03 Yes
这些字段在输出中以制表符分隔,但看起来有点奇怪。通过 时效果更好column -t
,但实际的选项卡会丢失:
$ awk -f script.awk file | column -t
ed00011 89 0.12 NA NA NA NA No
ed0002s 28 0.11 c3 3.1e-1 NA NA No
ed0001 22 0.37 NA NA 186_CR_NCR8_Ot 1.5e-6 No
ed0002a 596 0.89 c301 9.5e-2 17_CY7_Ot 0.03 Yes
答案3
可靠的方法
gawk '{
for(i = 4; i < 6; i++) {
if($i ~ /\(/) {
split($i, arr, "[()]")
$i = arr[1] "\t" arr[2]
} else {
$i = $i"\tNA"
}
}
print
}' OFS='\t' input.txt
不可靠,但正在研究您的样品、方法
sed 's/NA/&\tNA/g; s/(/\t/g; s/)//g' input.txt
该命令执行三个简单步骤:
s/NA/&\tNA/g
- 将全部替换为由制表符分隔的NA
双精度NA
。s/(/\t/g
- 将所有左括号替换为制表符。s/)//g
- 删除所有右括号。
它是不可靠的,因为它做了很多假设:括号只能出现在第 4 和 5 列中,NA
字符串只能出现在第 4 和 5 列中,第 4 和 5 列中的数字字符串始终具有c3(3.1e-1)
相似的格式。因此,如果它们只有唯一c3
的、没有括号的部分,则此sed
命令将不起作用。
但是,如果您的数据与您的样本严格相同,那么这就能完成工作。
输出
ed00011 89 0.12 NA NA NA NA No
ed0002s 28 0.11 c3 3.1e-1 NA NA No
ed0001 22 0.37 NA NA 186_CR_NCR8_Ot 1.5e-6 No
ed0002a 596 0.89 c301 9.5e-2 17_CY7_Ot 0.03 Yes