Awk 加入“#&引用;在匹配字符串的前8行前面

Awk 加入“#&引用;在匹配字符串的前8行前面,awk,sed,text-parsing,Awk,Sed,Text Parsing,这个问题有点让人困惑,所以我只举一个例子 假设我有以下情况: $ grep -P "locus_tag\tM715_1000193188" Genome.tbl -B1 -A8 193188 193066 gene locus_tag M715_1000193188 193188 193066 mRNA product hypothetical protein protein_id gnl|CorradiLab

这个问题有点让人困惑,所以我只举一个例子

假设我有以下情况:

$ grep -P "locus_tag\tM715_1000193188" Genome.tbl -B1 -A8
193188  193066  gene
            locus_tag   M715_1000193188
193188  193066  mRNA
            product hypothetical protein
            protein_id  gnl|CorradiLab|M715_1000193188
            transcript_id   gnl|CorradiLab|M715_mrna1000193188
193188  193066  CDS
        product hypothetical protein
        protein_id  gnl|CorradiLab|M715_1000193188
        transcript_id   gnl|CorradiLab|M715_mrna1000193188
我想在“轨迹标记M715_1000193188”后面的8行中添加“#”,以便修改后的文件如下所示:

193188  193066  gene
            locus_tag   M715_1000193188
#193188 193066  mRNA
#           product hypothetical protein
#           protein_id  gnl|CorradiLab|M715_1000193188
#           transcript_id   gnl|CorradiLab|M715_mrna1000193188
#193188 193066  CDS
#       product hypothetical protein
#       protein_id  gnl|CorradiLab|M715_1000193188
#       transcript_id   gnl|CorradiLab|M715_mrna1000193188
基本上,我有一个包含3000个不同基因座标签的文件,其中300个我需要注释掉mRNA和CDS特征,所以在基因座标签线后面的8行

有没有可能用sed实现这一点?文件中还有其他类型的信息需要保持不变

谢谢,
Adrian

如果您可以使用awk,这应该可以:

awk 'f&&f-- {$0="#"$0} /locus_tag/ {f=8} 1' file
193188  193066  gene
            locus_tag   M715_1000193188
#193188  193066  mRNA
#            product hypothetical protein
#            protein_id  gnl|CorradiLab|M715_1000193188
#            transcript_id   gnl|CorradiLab|M715_mrna1000193188
#193188  193066  CDS
#        product hypothetical protein
#        protein_id  gnl|CorradiLab|M715_1000193188
#        transcript_id   gnl|CorradiLab|M715_mrna1000193188
sed支持可以在这里做您想要做的事情的范围

sed -e '/locus_tag\tM715_1000193188/,+8s/^/#/' file
如注释中所述,此范围地址格式是特定于GNU的

$ cat tst.awk
BEGIN { split(tags,tmp); for (i in tmp) tagsA[tmp[i]] }
c&&c-- { $0 = "#" $0 }
($(NF-1) == "locus_tag") && ($NF in tagsA) { c=8 }
{ print }

$ awk -v tags="M715_1000193188 M715_1000193189 M715_1000193190" -f tst.awk file
193188  193066  gene
            locus_tag   M715_1000193188
#193188  193066  mRNA
#            product hypothetical protein
#            protein_id  gnl|CorradiLab|M715_1000193188
#            transcript_id   gnl|CorradiLab|M715_mrna1000193188
#193188  193066  CDS
#        product hypothetical protein
#        protein_id  gnl|CorradiLab|M715_1000193188
#        transcript_id   gnl|CorradiLab|M715_mrna1000193188
只需列出您关心的所有300个轨迹标记值,如上所示为3个示例。

这可能适用于您(GNU-sed):


这将从标记文件创建一个sed脚本,并在标记匹配后的八行前面加上前缀

很好,很有效!如何直接在文件中进行更改?我需要这样做300次,所以是否有任何方式,使改变“文件”直接每次我进行编辑?假设我有一个for循环,其中$I是轨迹名,awk看起来像这个awk'f&&f--{$0=“#”$0}/locus_tag\t$I/{f=8}1'文件,使
awk
更新原始文件do:
awk'commands'文件>tmp和&mv tmp文件
。如果你有
gawk
=`4.1',你可以使用
gawk-i
或传递awk所有轨迹值,并在一次传递输入文件中进行所有更改。我遇到了一点麻烦。某些轨迹编号,例如M715_80001,由于与其他轨迹编号(例如M715_8000123 M715_80001654)部分匹配,因此存在问题。我如何调整它以获得精确匹配?我尝试添加一个\n字符,但它不起作用:awk'f&&f--{$0=“#”$0}/locus_-tag\tM715_80001\n/{f=8}1'你可以做:
awk'f&&f--{$0=“#”$0}$1=“locus_-tag”和&$2=“M715_-80001”{f=8}1'文件
我喜欢它。除此之外:sed直接理解
\t
。范围的
/pattern/,+8
形式是特定于GNU的;注意这一点可能是明智的。此解决方案注释字符串后面的8行以及找到字符串的行。是否可以不注释找到字符串的行?谢谢。。。好问题。我不确定塞德能轻易做到这一点。vim支持这种范围。我想你需要一个标签和一个替换测试或者类似的东西来测试sed。除了赛前的两行,有没有其他方法可以做到这一点?我尝试了-2s而不是+8s,但没有成功。sed绝对不能像那样倒退。我也不知道sed在范围上做“数学”。vim可以做这两件事,但不适合大文件。您可以通过手动保持行的滑动窗口来使用awk实现这一点,但我不知道有什么可以以流式方式实现这一点(可能是perl,但我不知道)。
sed 's/.*/\\#locus_tag\\s*&#,+9{\\#locus_tag\\s*&#n;s|^|#|}/' tag_file |
sed -i -f - file