gawk to awk中的区间表达式。

问题描述 投票:1回答:1

我希望这是一个简单的修复

我原来写了一个利用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 

希望对其他人有所帮助!

regex awk expression intervals
1个回答
2
投票

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.

2
投票

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

1
投票

听起来你想要的是:

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
© www.soinside.com 2019 - 2024. All rights reserved.