【问题标题】:Use awk to find regex of variable length and edit following lines based on length found使用 awk 查找可变长度的正则表达式并根据找到的长度编辑以下行
【发布时间】:2015-06-03 19:48:18
【问题描述】:

我正在尝试使用 awk 编辑一个 fastq 文件。

@someheader example fastq file
TGTACTTAGAGAAGCGC
+
BDDADHHIHHHIICHIG
@nextheader
CCGTAACCTGGGCAGTG
+
DDDDDHIIIIIIIIIII

我想要实现的是:

  • 查找以下正则表达式:/AGATCGGAAG[ATGC]{0,24}$/ - 如果可能,仅在实际可能找到的行中(例如第 2、6、10 行,x+2%4=0 基本上)
  • 如果找到,删除匹配项
  • 然后删除当前行后2行末尾相同数量的字符

到目前为止,根据正则表达式编辑一行对我来说没有问题,我使用的是:

awk '{ gsub(/AGATCGGAAG[ATGC]{0,24}$/, ""); print RLENGTH }'

但我不知道如何在 2 行后删除相同数量的字符。 我非常缺乏经验,才开始学习 awk,所以欢迎任何帮助。

问候

编辑:这是一个包含上述模式的示例

@HWI-ST558:329:H3K2GBCXX:1:1101:5408:2985 1:N:0:ATCACG
CCTCCCGGTCGGTGCTGAGAGAGACTGGGCTCTCTGGAACTCCACCACCGAGATCGGAAGAG
+
HHHIIIIHDHIIIHIIGHHHIHFHHCHHIE?GHHGHF?GECFEEHFHHHCHDHHHFEEHHHH

这应该是输出:

@HWI-ST558:329:H3K2GBCXX:1:1101:5408:2985 1:N:0:ATCACG
CCTCCCGGTCGGTGCTGAGAGAGACTGGGCTCTCTGGAACTCCACCACCG
+
HHHIIIIHDHIIIHIIGHHHIHFHHCHHIE?GHHGHF?GECFEEHFHHHC

该文件包含 4000 万个这样的条目,其中约 250k 包含模式

【问题讨论】:

  • 请展示一些实际包含该模式的示例数据。
  • 也许匹配功能会有所帮助。它将 RSTART 和 RLENGTH 设置为与某个正则表达式匹配的字符串部分的开始索引和长度。 RLENGTH 会告诉你匹配了多少个字符,你可以将它保存在一个变量中:

标签: linux bash shell awk fastq


【解决方案1】:

这可能有效,但由于您的示例输入不包含任何与正则表达式匹配的行并且您没有提供任何预期的输出,因此它当然未经测试:

NR%4 == 2 { match($0,/AGATCGGAAG[ATGC]{0,24}$/) }
RSTART && (NR%4 ~ /^[02]$/) { $0 = substr($0,1,RSTART-1) }
{ print }

【讨论】:

  • 我问了一个关于在文件中查找最大数量的问题,并且有一些关于使用awk 的最佳方法的讨论。让您的专业知识看到它会很棒! stackoverflow.com/q/30592249
  • 不会在下一行不匹配时重置 RSTART,因此不会为 2 行之后设置?如果没有,那么这不会删除每隔一行的开头。最后,模数 4 永远不会是 4,所以这个位 NR%4 ~ /^[24] 并没有真正的意义。
  • @User112638726 将 [24] 更改为 [02]。未经测试 == 未经测试。仅当 NR%4 为 2 时才会设置/清除 RSTART,而无需过多考虑我认为正确的方法。不过,再次未经测试。
  • 谢谢,这很有效,并且完全符合我的要求。您能否更详细地解释您的陈述,因为我想学习! @ed morton
  • @voiDnyx 在手册页(例如gnu.org/software/gawk/manual/gawk.html)中查找各种构造(NR、match、RSTART、substr),看看你是否能弄清楚其中的一些,我会很高兴回答具体问题。
【解决方案2】:

Perl 解决方案:

#! /usr/bin/perl
use warnings;
use strict;

my $length;
while (<>) {                            # Read line by line.
    if (2 == $. % 4) {
        $length = length $1 if s/(TAGAGA[ACTG]{0,7})$//;
    } elsif (0 == $. % 4 && $length) {  # We should shorten this line.
        s/.{$length}$//;
        undef $length;                  # Done.
    }
    print;
}

【讨论】:

    【解决方案3】:

    有点长,但应该可以:

    awk '
        BEGIN {
            n=-1
            pat="AGATCGGAAG[ATGC]{0,24}$"
        }
        NR%4==2 && $0 ~ pat {
            match($0, pat);
            gsub(pat, "");
            n=NR+2;
        }
        NR==n {
            print substr($0,1,RSTART-1) substr($0,RSTART+RLENGTH)
            next
        }
        { print }
    
    '
    

    【讨论】:

      猜你喜欢
      • 2016-03-03
      • 2015-06-23
      • 2016-04-04
      • 1970-01-01
      • 2015-04-02
      • 1970-01-01
      • 2020-04-12
      • 2014-11-04
      • 2011-11-16
      相关资源
      最近更新 更多