gawk 到 awk 中的区间表达式
Interval expressions in gawk to awk
我希望这是一个简单的修复
我最初使用 gawk 编写了一个干净简单的脚本,我首先使用它是因为当我解决原始问题时,我发现了。我现在需要调整它以仅使用 awk。
样本file.fasta:
>gene1
>gene235
ATGCTTAGATTTACAATTCAGAAATTCCTGGTCTATTAACCCTCCTTCACTTTTCACTTTTCCCTAACCCTTCAAAATTTTATATCCAATCTTCTCACCCTCTACAATAATACATTTATTATCCTCTTACTTCAAAATTTTT
>gene335
ATGCTCCTTCTTAATCTAAACCTTCAAAATTTTCCCCCTCACATTTATCCATTATCACCTTCATTTCGGAATCCTTAACTAAATACAATCATCAACCATCTTTTAACATAACTTCTTCAAAATTTTACCAACTTACTATTGCTTCAAAATTTTTCAT
>gene406
ATGTACCACACACCCCCATCTTCCATTTTCCCTTTATTCTCCTCACCTCTACAATCCCCTTAATTCCTCTTCAAAATTTTTGGAGCCCTTAACTTTCAATAACTTCAAAATTTTTCACCATACCAATAATATCCCTCTTCAAAATTTTCCACACTCACCAAC
gawk '/[ACTG]{21,}GG/{print a; print}{a=[=10=]}' file.fasta >"species_precrispr".fasta
我知道 awk 的工作原理如下:
awk '/[ACTG]GG/{print a; print}{a=[=11=]}' file.fasta >"species_precrispr".fasta
因此罪魁祸首是 {21,} 的区间表达式
我想要它做的是搜索它以匹配包含我的 "GG" 匹配剩余至少 21 个核苷酸的每一行。
有人能帮忙吗?
编辑:
感谢所有帮助:
有各种有效的解决方案。要回复一些评论,请提供一个更基本的初始输出示例和所达到的预期效果...
awk 命令之前:
猫 file1.fasta
>gene1
ATGCCTTAACTTTCAATAACTGG
>gene2
ATGGGTGCCTTAACTTTCAATAACTG
>gene3
ATGTCAAAATTTTTCATTTCAAT
>gene4
ATCCTTTTTTTTGGGTCAAAATTAAA
>gene5
ATGCCTTAACTTTCAATAACTTTTTAAAATTTTTGG
以下代码都产生了相同的期望输出:
原码
gawk '/[ACTG]{21,}GG/{print a; print}{a=[=13=]}' file1.fasta
在原始 awk 版本中添加间隔函数的细微修改 >3.x.x
awk --re-interval'/[ACTG]{21,}GG/{print a; print}{a=[=14=]}' file1.fasta
允许修改 val 和正确的输出,未经测试但应该适用于较低版本的 awk
awk -v usr_count="21" '/gene/{id=[=15=];next} match([=15=],/.*GG/){val=substr([=15=],RSTART,RLENGTH-2);if(gsub(/[ACTG]/,"&",val)>= usr_count){print id ORS [=15=]};id=""}' file1.fasta
awk --re-interval '/^>/ && seq { if (match(seq,"[ACTG]{21,}GG")) print ">" name ORS seq ORS} /^>/{name=[=15=]; seq=""; next} {seq = seq [=15=] } END { if (match(seq,"[ACTG]{21,}GG")) print ">" name ORS seq ORS }' file1.fasta
期望的输出:仅抓取基因名称和匹配 GG 之前具有 21 个核苷酸的序列序列
>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
希望这对其他人有帮助!
编辑: 根据 OP 评论,也需要打印基因 ID,然后尝试以下操作。
awk '
/gene/{
id=[=10=]
next
}
match([=10=],/.*GG/){
val=substr([=10=],RSTART,RLENGTH-2)
if(gsub(/[ACTG]/,"&",val)>=21){
print id ORS [=10=]
}
id=""
}
' Input_file
或根据 OP 的要求,上述解决方案的单行形式:
awk '/gene/{id=[=11=];next} match([=11=],/.*GG/){val=substr([=11=],RSTART,RLENGTH-2);if(gsub(/[ACTG]/,"&",val)>=21){print id ORS [=11=]};id=""}' Input_file
您能否尝试仅使用显示的示例进行以下编写和测试。
awk '
match([=12=],/.*GG/){
val=substr([=12=],RSTART,RLENGTH-2)
if(gsub(/[ACTG]/,"&",val)>=21){
print
}
}
' Input_file
或更通用的方法,其中创建了一个变量,用户可以在其中提及用户希望匹配的值应该出现在 GG 之前。
awk -v usr_count="21" '
match([=13=],/.*GG/){
val=substr([=13=],RSTART,RLENGTH-2)
if(gsub(/[ACTG]/,"&",val)>=usr_count){
print
}
}
' Input_file
解释:为以上添加详细解释。
awk ' ##Starting awk program from here.
match([=14=],/.*GG/){ ##Using Match function to match everything till GG in current line.
val=substr([=14=],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 时经常会忽视一个问题。当您有多行序列时,您的 match 可能覆盖多行。为此,您需要先组合您的序列。
用 awk 处理 FASTA 文件的最简单方法是建立一个名为 name
的变量和一个名为 seq
的变量。每次阅读完整序列时,您都可以对其进行处理。请注意,为了获得最佳处理方式,序列应存储为连续字符串,并且不应包含任何换行符或空白符。用于处理 fasta 的通用 awk,如下所示:
awk '/^>/ && seq { **process_sequence_here** }
/^>/{name=[=11=]; seq=""; next}
{seq = seq [=11=] }
END { **process_sequence_here** }' file.fasta
在当前案例中,您的序列处理如下所示:
awk '/^>/ && seq { if (match(seq,"[ACTG]{21,}GG")) print ">" name ORS seq ORS}
/^>/{name=[=12=]; seq=""; next}
{seq = seq [=12=] }
END { if (match(seq,"[ACTG]{21,}GG")) print ">" name ORS seq ORS }' file.fasta
听起来你想要的是:
awk 'match([=10=],/[ACTG]+GG/) && RLENGTH>22{print a; print} {a=[=10=]}' file
但考虑到您提供的样本输入,这可能就是您所需要的全部内容:
awk 'match([=11=],/.*GG/) && RLENGTH>22{print a; print} {a=[=11=]}' file
它们都可以在任何 awk 中工作。
使用更新后的样本输入:
$ awk 'match([=12=],/.*GG/) && RLENGTH>22{print a; print} {a=[=12=]}' file
>gene1
ATGCCTTAACTTTCAATAACTGG
>gene5
ATGCCTTAACTTTCAATAACTTTTTAAAATTTTTGG
我希望这是一个简单的修复
我最初使用 gawk 编写了一个干净简单的脚本,我首先使用它是因为当我解决原始问题时,我发现了。我现在需要调整它以仅使用 awk。
样本file.fasta:
>gene1
>gene235
ATGCTTAGATTTACAATTCAGAAATTCCTGGTCTATTAACCCTCCTTCACTTTTCACTTTTCCCTAACCCTTCAAAATTTTATATCCAATCTTCTCACCCTCTACAATAATACATTTATTATCCTCTTACTTCAAAATTTTT
>gene335
ATGCTCCTTCTTAATCTAAACCTTCAAAATTTTCCCCCTCACATTTATCCATTATCACCTTCATTTCGGAATCCTTAACTAAATACAATCATCAACCATCTTTTAACATAACTTCTTCAAAATTTTACCAACTTACTATTGCTTCAAAATTTTTCAT
>gene406
ATGTACCACACACCCCCATCTTCCATTTTCCCTTTATTCTCCTCACCTCTACAATCCCCTTAATTCCTCTTCAAAATTTTTGGAGCCCTTAACTTTCAATAACTTCAAAATTTTTCACCATACCAATAATATCCCTCTTCAAAATTTTCCACACTCACCAAC
gawk '/[ACTG]{21,}GG/{print a; print}{a=[=10=]}' file.fasta >"species_precrispr".fasta
我知道 awk 的工作原理如下:
awk '/[ACTG]GG/{print a; print}{a=[=11=]}' file.fasta >"species_precrispr".fasta
因此罪魁祸首是 {21,} 的区间表达式
我想要它做的是搜索它以匹配包含我的 "GG" 匹配剩余至少 21 个核苷酸的每一行。
有人能帮忙吗?
编辑:
感谢所有帮助: 有各种有效的解决方案。要回复一些评论,请提供一个更基本的初始输出示例和所达到的预期效果...
awk 命令之前: 猫 file1.fasta
>gene1
ATGCCTTAACTTTCAATAACTGG
>gene2
ATGGGTGCCTTAACTTTCAATAACTG
>gene3
ATGTCAAAATTTTTCATTTCAAT
>gene4
ATCCTTTTTTTTGGGTCAAAATTAAA
>gene5
ATGCCTTAACTTTCAATAACTTTTTAAAATTTTTGG
以下代码都产生了相同的期望输出:
原码
gawk '/[ACTG]{21,}GG/{print a; print}{a=[=13=]}' file1.fasta
在原始 awk 版本中添加间隔函数的细微修改 >3.x.x
awk --re-interval'/[ACTG]{21,}GG/{print a; print}{a=[=14=]}' file1.fasta
允许修改 val 和正确的输出,未经测试但应该适用于较低版本的 awk
awk -v usr_count="21" '/gene/{id=[=15=];next} match([=15=],/.*GG/){val=substr([=15=],RSTART,RLENGTH-2);if(gsub(/[ACTG]/,"&",val)>= usr_count){print id ORS [=15=]};id=""}' file1.fasta
awk --re-interval '/^>/ && seq { if (match(seq,"[ACTG]{21,}GG")) print ">" name ORS seq ORS} /^>/{name=[=15=]; seq=""; next} {seq = seq [=15=] } END { if (match(seq,"[ACTG]{21,}GG")) print ">" name ORS seq ORS }' file1.fasta
期望的输出:仅抓取基因名称和匹配 GG 之前具有 21 个核苷酸的序列序列
>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
希望这对其他人有帮助!
编辑: 根据 OP 评论,也需要打印基因 ID,然后尝试以下操作。
awk '
/gene/{
id=[=10=]
next
}
match([=10=],/.*GG/){
val=substr([=10=],RSTART,RLENGTH-2)
if(gsub(/[ACTG]/,"&",val)>=21){
print id ORS [=10=]
}
id=""
}
' Input_file
或根据 OP 的要求,上述解决方案的单行形式:
awk '/gene/{id=[=11=];next} match([=11=],/.*GG/){val=substr([=11=],RSTART,RLENGTH-2);if(gsub(/[ACTG]/,"&",val)>=21){print id ORS [=11=]};id=""}' Input_file
您能否尝试仅使用显示的示例进行以下编写和测试。
awk '
match([=12=],/.*GG/){
val=substr([=12=],RSTART,RLENGTH-2)
if(gsub(/[ACTG]/,"&",val)>=21){
print
}
}
' Input_file
或更通用的方法,其中创建了一个变量,用户可以在其中提及用户希望匹配的值应该出现在 GG 之前。
awk -v usr_count="21" '
match([=13=],/.*GG/){
val=substr([=13=],RSTART,RLENGTH-2)
if(gsub(/[ACTG]/,"&",val)>=usr_count){
print
}
}
' Input_file
解释:为以上添加详细解释。
awk ' ##Starting awk program from here.
match([=14=],/.*GG/){ ##Using Match function to match everything till GG in current line.
val=substr([=14=],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 时经常会忽视一个问题。当您有多行序列时,您的 match 可能覆盖多行。为此,您需要先组合您的序列。
用 awk 处理 FASTA 文件的最简单方法是建立一个名为 name
的变量和一个名为 seq
的变量。每次阅读完整序列时,您都可以对其进行处理。请注意,为了获得最佳处理方式,序列应存储为连续字符串,并且不应包含任何换行符或空白符。用于处理 fasta 的通用 awk,如下所示:
awk '/^>/ && seq { **process_sequence_here** }
/^>/{name=[=11=]; seq=""; next}
{seq = seq [=11=] }
END { **process_sequence_here** }' file.fasta
在当前案例中,您的序列处理如下所示:
awk '/^>/ && seq { if (match(seq,"[ACTG]{21,}GG")) print ">" name ORS seq ORS}
/^>/{name=[=12=]; seq=""; next}
{seq = seq [=12=] }
END { if (match(seq,"[ACTG]{21,}GG")) print ">" name ORS seq ORS }' file.fasta
听起来你想要的是:
awk 'match([=10=],/[ACTG]+GG/) && RLENGTH>22{print a; print} {a=[=10=]}' file
但考虑到您提供的样本输入,这可能就是您所需要的全部内容:
awk 'match([=11=],/.*GG/) && RLENGTH>22{print a; print} {a=[=11=]}' file
它们都可以在任何 awk 中工作。
使用更新后的样本输入:
$ awk 'match([=12=],/.*GG/) && RLENGTH>22{print a; print} {a=[=12=]}' file
>gene1
ATGCCTTAACTTTCAATAACTGG
>gene5
ATGCCTTAACTTTCAATAACTTTTTAAAATTTTTGG