我希望这是一个简单的修复
我原来写了一个利用gawk的干净简单的脚本,我首先使用了这个,因为当我在解决原来的问题时是我发现的。我现在需要把它改编成只使用awk。
sample file.fasta.Fasta.Fasta.Fasta.Fasta.Fasta.Fasta.Fasta.Fasta.Fasta.Fasta.Fasta.Fasta.Fasta.Fasta.Fasta.Fasta:
>gene1
>gene235
ATGCTTAGATTTACAATTCAGAAATTCCTGGTCTATTAACCCTCCTTCACTTTTCACTTTTCCCTAACCCTTCAAAATTTTATATCCAATCTTCTCACCCTCTACAATAATACATTTATTATCCTCTTACTTCAAAATTTTT
>gene335
ATGCTCCTTCTTAATCTAAACCTTCAAAATTTTCCCCCTCACATTTATCCATTATCACCTTCATTTCGGAATCCTTAACTAAATACAATCATCAACCATCTTTTAACATAACTTCTTCAAAATTTTACCAACTTACTATTGCTTCAAAATTTTTCAT
>gene406
ATGTACCACACACCCCCATCTTCCATTTTCCCTTTATTCTCCTCACCTCTACAATCCCCTTAATTCCTCTTCAAAATTTTTGGAGCCCTTAACTTTCAATAACTTCAAAATTTTTCACCATACCAATAATATCCCTCTTCAAAATTTTCCACACTCACCAAC
gawk '/[ACTG]{21,}GG/{print a; print}{a=$0}' file.fasta >"species_precrispr".fasta
我知道awk的工作原理是:
awk '/[ACTG]GG/{print a; print}{a=$0}' file.fasta >"species_precrispr".fasta
因此,罪魁祸首是{21,}的区间表达式。
我想让它做的是搜索是让它匹配每一行至少包含我的 "GG "匹配剩下的21个核苷酸。
有谁能帮忙吗?
编辑:谢谢。
谢谢大家的帮助:有各种不同的解决方案,工作。为了回复一些评论一个更基本的例子,初始输出和达到的预期效果......
在awk命令之前:cat file1.fasta
>gene1
ATGCCTTAACTTTCAATAACTGG
>gene2
ATGGGTGCCTTAACTTTCAATAACTG
>gene3
ATGTCAAAATTTTTCATTTCAAT
>gene4
ATCCTTTTTTTTGGGTCAAAATTAAA
>gene5
ATGCCTTAACTTTCAATAACTTTTTAAAATTTTTGG
以下代码都产生了相同的预期输出。
原代码
gawk '/[ACTG]{21,}GG/{print a; print}{a=$0}' file1.fasta
稍微修改,添加间隔函数到原来的awk版本>3.x.x。
awk --re-interval'/[ACTG]{21,}GG/{print a; print}{a=$0}' file1.fasta
允许修改val和正确的输出,未经测试,但应该可以在较低版本的awk中使用。
awk -v usr_count="21" '/gene/{id=$0;next} match($0,/.*GG/){val=substr($0,RSTART,RLENGTH-2);if(gsub(/[ACTG]/,"&",val)>= usr_count){print id ORS $0};id=""}' file1.fasta
awk --re-interval '/^>/ && seq { if (match(seq,"[ACTG]{21,}GG")) print ">" name ORS seq ORS} /^>/{name=$0; seq=""; next} {seq = seq $0 } END { if (match(seq,"[ACTG]{21,}GG")) print ">" name ORS seq ORS }' file1.fasta
希望的输出:只抓取基因名称和序列的21个核苷酸的序列,然后再匹配GG
>gene1
ATGCCTTAACTTTCAATAACTGG
>gene5
ATGCCTTAACTTTCAATAACTTTTTAAAATTTTTGG
最后只想说明一下被抛弃的线条
>gene2
ATG-GG-TGCCTTAACTTTCAATAACTG # only 3 nt prior to any GG combo
>gene3
ATGTCAAAATTTTTCATTTCAAT # No GG match found
>gene4
ATCCTTTTTTTTGGGTCAAAATTAAA # only 14 nt prior to any GG combo
希望对其他人有所帮助!
EDIT: 根据OP的评论,需要打印基因ID,然后尝试以下。
awk '
/gene/{
id=$0
next
}
match($0,/.*GG/){
val=substr($0,RSTART,RLENGTH-2)
if(gsub(/[ACTG]/,"&",val)>=21){
print id ORS $0
}
id=""
}
' Input_file
或者按照OP的要求,以单行本的形式解决上述问题。
awk '/gene/{id=$0;next} match($0,/.*GG/){val=substr($0,RSTART,RLENGTH-2);if(gsub(/[ACTG]/,"&",val)>=21){print id ORS $0};id=""}' Input_file
你能不能试试下面的方法,只用显示的样本编写和测试。
awk '
match($0,/.*GG/){
val=substr($0,RSTART,RLENGTH-2)
if(gsub(/[ACTG]/,"&",val)>=21){
print
}
}
' Input_file
或者采用更通用的方法,创建一个变量,用户可以在变量中提到用户正在寻找匹配的值,该变量应该在GG之前出现。
awk -v usr_count="21" '
match($0,/.*GG/){
val=substr($0,RSTART,RLENGTH-2)
if(gsub(/[ACTG]/,"&",val)>=usr_count){
print
}
}
' Input_file
解释。 为上述内容添加详细解释。
awk ' ##Starting awk program from here.
match($0,/.*GG/){ ##Using Match function to match everything till GG in current line.
val=substr($0,RSTART,RLENGTH-2) ##Storing sub-string of current line from RSTART till RLENGTH-2 into variable val here.
if(gsub(/[ACTG]/,"&",val)>=21){ ##Checking condition if global substitution of ACTG(with same value) is greater or equal to 21 then do following.
print ##Printing current line then.
}
}
' Input_file ##Mentioning Input_file name here.
GNU awk从3.0版本开始接受正则表达式中的间隔表达式。但是,从4.0版本开始,区间表达式才被默认启用。如果你使用的是awk 3.x.x,你必须使用标志 --re-interval
来启用它们。
awk --re-interval '/a{3,6}/{print}' file
在使用FASTA文件和使用awk时,有一个问题经常被人们忽略。当你有多行序列时,有可能你的 匹配 是覆盖多行。为此,你需要先组合你的序列。
用awk处理FASTA文件最简单的方法是建立一个叫做 name
和一个叫做 seq
. 每次读取一个完整的序列,就可以对其进行处理。请注意,为了获得最佳的处理方式,序列,应该被存储为一个continue字符串,并且不包含任何换行或空格。一个用于处理fasta的通用awk,看起来像这样。
awk '/^>/ && seq { **process_sequence_here** }
/^>/{name=$0; seq=""; next}
{seq = seq $0 }
END { **process_sequence_here** }' file.fasta
在目前的情况下,你的序列处理看起来是这样的:
awk '/^>/ && seq { if (match(seq,"[ACTG]{21,}GG")) print ">" name ORS seq ORS}
/^>/{name=$0; seq=""; next}
{seq = seq $0 }
END { if (match(seq,"[ACTG]{21,}GG")) print ">" name ORS seq ORS }' file.fasta
听起来你想要的是:
awk 'match($0,/[ACTG]+GG/) && RLENGTH>22{print a; print} {a=$0}' file
但根据你提供的样本输入,这可能是你所需要的全部。
awk 'match($0,/.*GG/) && RLENGTH>22{print a; print} {a=$0}' file
它们在任何awk中都能工作。
使用你更新的样本输入。
$ awk 'match($0,/.*GG/) && RLENGTH>22{print a; print} {a=$0}' file
>gene1
ATGCCTTAACTTTCAATAACTGG
>gene5
ATGCCTTAACTTTCAATAACTTTTTAAAATTTTTGG