在bash中将字符串替换为一定的格式



我有一个这样的文件。它是一个7列制表符文件,分隔符为一个空格(sep=" ")。

然而,在第4列中,是一个包含一些单词的字符串,其中也包含空格。最后三列是数字

test_find.txt

A UTR3 0.760 Sterile alpha motif domain|Sterile alpha motif domain;Sterile alpha motif domain . . 0.0007
G intergenic 0.673 BTB/POZ domain|BTB/POZ domain|BTB/POZ domain . . 0.0015

我想替换空间强调(例如替换"无菌α基序域";以"Sterile_alpha_motif_domain"。首先,找到以字母开头,以"|"结尾的模式,然后将其视为一个字符串,并将所有空格替换为"_"。然后移动到下一行,找到下一个模式。(有更简单的方法吗?)

我可以使用sed -i -e 's/Sterile alpha motif domain/Sterile_alpha_motif_domain/g' test_find.txt仅第一行,但不能泛化它.

我试图找到使用sed -n 's/^[^[a-z]]*{(.*)\[^|]*$/1/p' test_find.txt的所有模式,但不工作。

有人能帮我吗?我想要这样的输出:

A UTR3 0.760 Sterile_alpha_motif_domain|Sterile_alpha_motif_domain;Sterile_alpha_motif_domain . . 0.0007
G intergenic 0.673 BTB/POZ_domain|BTB/POZ_domain . . 0.0015

谢谢! !

我们需要两步处理:首先提取第四列,这可能包含空间;接下来用下划线替换第四列中的空格。

WithGNU awk:

gawk '{
if (match($0, /^(([^ ]+ ){3})(.+)(( [0-9.]+){3})$/, a)) {
gsub(/ /, "_", a[3])
print a[1] a[3] a[4]
}
}' test_find.txt

输出:

A UTR3 0.760 Sterile_alpha_motif_domain|Sterile_alpha_motif_domain;Sterile_alpha_motif_domain . . 0.0007
G intergenic 0.673 BTB/POZ_domain|BTB/POZ_domain|BTB/POZ_domain . . 0.0015
  • 正则表达式^(([^ ]+ ){3})(.+)(( [0-9.]+){3})$匹配一行捕获每个submatch。
  • 第三个参数(GNU awk扩展)a是一个数组名分配给捕获组。A[1]保存第1 -3列,a[3]保存第4列,a[4]保存第5 -7列。
  • gsub函数将空格替换为下划线。
  • 然后将列连接并打印。

假设您在最后一个整数列的末尾有特殊字符,您可以尝试此sed

$ sed -E 's~([[:alpha:]/]+) ~1_~g;s/_([[:punct:]])/ 1/g' input_file
0.760 Sterile_alpha_motif_domain|Sterile_alpha_motif_domain;Sterile_alpha_motif_domain . . 0.0007
0.673 BTB/POZ_domain|BTB/POZ_domain|BTB/POZ_domain . . 0.0015

无需对每个字段的内容进行任何假设,您可以通过计算行首和行尾的每个字段中的字符数(+字段分隔符的数量)来'蛮力'获得预期的结果,并使用它来操作'第四列',例如

awk '{start=length($1)+length($2)+length($3)+4; end=length($0)-length($NF)-length($(NF-1))-length($(NF-2))-length($1)-length($2)-length($3)-6; text=substr($0, start, end); gsub(" ", "_", text); print $1, $2, $3, text, $(NF-2), $(NF-1), $NF}' test.txt

"整洁"版本:

awk '{
start=length($1)+length($2)+length($3)+4
end=length($0)-length($NF)-length($(NF-1))-length($(NF-2))-length($1)-length($2)-length($3)-6
text=substr($0, start, end)
gsub(" ", "_", text)
print $1, $2, $3, text, $(NF-2), $(NF-1), $NF
}' test.txt
A UTR3 0.760 Sterile_alpha_motif_domain|Sterile_alpha_motif_domain;Sterile_alpha_motif_domain . . 0.0007
G intergenic 0.673 BTB/POZ_domain|BTB/POZ_domain|BTB/POZ_domain . . 0.0015

击穿:

awk '{
# How many characters are there before column 4 begins (length of each field + total count of field separators (in this case, "4"))
start=length($1)+length($2)+length($3)+4;
# How many characters are there in column 4 (total - (first 3 fields + last 3 fields + total field separators (6)))
end=length($0)-length($NF)-length($(NF-1))-length($(NF-2))-length($1)-length($2)-length($3)-6;
# Use the substr function to define column 4
text=substr($0, start, end);
# Substitute spaces for underscores in column 4
gsub(" ", "_", text);
# Print everything
print $1, $2, $3, text, $(NF-2), $(NF-1), $NF
}' test.txt