我有一个DNA序列的'测试'文件,每个都有一个标题或ID,如下所示:
>new
ATCGGC
>two
ACGGCTGGG
>tre
ACAACGGTAGCTACTATACGGTCGTATTTTTT
我想在匹配之前和之后打印每个连续字符串的长度给定字符串,例如CGG
输出将如下所示:
>new
2 1
>two
1 5
>tre
4 11 11
或者可以只有每行匹配前后的字符长度。
2 1
1 5
4 11 11
我第一次尝试使用sed在找到'>'后打印下一行,然后找到每个grep匹配“CGG”的字节偏移量,我将用它来转换为长度,但这产生了以下结果:
sed -n '/>/ {n;p}' test | grep -aob "CGG"
2:CGG
8:CGG
21:CGG
35:CGG
基本上,grep为每个匹配打印字节偏移,向上计数,而我希望每行独立的字节偏移(即在每行之后重置)。
我想我也需要使用sed进行搜索,因为它逐行操作,但我不知道如何抵消给定字符串中的字节偏移或字符。
非常感谢任何帮助。
答案 0 :(得分:7)
通过使用给定的字符串作为awk中的字段分隔符,可以轻松地遍历每行上的字段并打印它们的长度。 (以>
开头的行我们只是按原样打印。)
这为您的示例数据提供了所需的输出,但您可能希望检查边缘情况,例如以CGG
开头,以CGG
结尾,仅包含CGG
等。
$ awk -F CGG '/^>/ {print; next} {for (i=1; i<=NF; ++i) {printf "%s%s", length($i), (i==NF)?"\n":" "}}' file.txt
>new
2 1
>two
1 5
>tre
4 11 11
awk -F CGG
使用“CGG”作为字段分隔符调用awk。这会将每一行解析为一组字段,这些字段由字符串“CGG”的每个(如果有)出现。 “CGG”字符串本身既不包含在任何字段中,也不包含在任何字段中。
因此,行ACAACGGTAGCTACTATACGGTCGTATTTTTT
被解析为三个字段:ACAA
,TAGCTACTATA
和TCGTATTTTTT
,由$1
表示在awk程序中,{分别为{1}}和$2
。
'/ ^&gt; / {print;下一个}
此模式/操作告诉awk如果行以$3
开头打印行并立即转到下一行输入,而不考虑awk程序中的任何进一步模式或操作。
{for(i = 1; i&lt; = NF; ++ i){printf“%s%s”,length($ i),(i == NF)?“\ n”:“”}}
如果我们到达此操作,我们知道该行不以>
开头(见上文)。由于只有一个动作而没有模式,因此对于到达此处的每一行输入执行动作。
for循环遍历所有字段(>
是一个特殊的awk变量,包含当前行中的字段数)并打印它们的长度。通过检查我们是否到达最后一个字段,我们知道是打印换行还是仅打印空格。