grep 排除模式并排除前面的 2 行



我有一个文件,想使用 grep 来排除模式。但我也想删除每场比赛的前 2 行(不包括在内(。我该怎么做?

我尝试过的:

cat file.txt
Sequence: MG719312_IGHV1-8*03_Homosapiens_F_V-REGION_127..422_296nt_1_____296+0=296___     from: 1   to: 296
  Start     End  Strand Pattern                 Mismatch Sequence
    217     225       + pattern:AA[CT]NNN[AT]CN        . aacacctcc
Sequence: M99648_IGHV2-26*01_Homosapiens_F_V-REGION_164..464_301nt_1_____301+0=301___     from: 1   to: 301
  Start     End  Strand Pattern                 Mismatch Sequence
    176     184       + pattern:AA[CT]NNN[AT]CN        . aatcctaca
# With grep -v I can remove the line with pattern
grep -v "[acgt]{3}cc[acgt][acgt]{3}" file.txt
Sequence: MG719312_IGHV1-8*03_Homosapiens_F_V-REGION_127..422_296nt_1_____296+0=296___ from: 1 to: 296
Start End Strand Pattern Mismatch Sequence
217 225 + pattern:AA[CT]NNN[AT]CN . aacacctcc
Sequence: M99648_IGHV2-26*01_Homosapiens_F_V-REGION_164..464_301nt_1_____301+0=301___ from: 1 to: 301
Start End Strand Pattern Mismatch Sequence
# But using -B 2 does not work here
grep -B 2 -v "[acgt]{3}cc[acgt][acgt]{3}" file.txt
Sequence: MG719312_IGHV1-8*03_Homosapiens_F_V-REGION_127..422_296nt_1_____296+0=296___ from: 1 to: 296
Start End Strand Pattern Mismatch Sequence
217 225 + pattern:AA[CT]NNN[AT]CN . aacacctcc
Sequence: M99648_IGHV2-26*01_Homosapiens_F_V-REGION_164..464_301nt_1_____301+0=301___ from: 1 to: 301
Start End Strand Pattern Mismatch Sequence

任何想法如何删除每场比赛的前 2 行?

GNU sed上测试,语法/功能可能因其他实现而异

sed -E 'N;N; /[acgt]{3}cc[acgt][acgt]{3}/d' ip.txt
  • -E使用 ERE,某些 sed 版本需要 -r 而不是-E
  • N;N将另外两行追加到图案空间
  • 如果此条件匹配,则/[acgt]{3}cc[acgt][acgt]{3}/d删除
    • 请注意,这将尝试匹配三行中任何位置的正则表达式......此外,[acgt][acgt]{3}可以简化为[acgt]{4}
    • /n.*n.*[acgt]{3}cc[acgt][acgt]{3}/d将限制为仅匹配第 3 行

您所需要的只是:

tac file | awk '/regexp/{c=3} !(c&&c--)' | tac

显然,regexp设置为您要匹配的任何正则表达式,并将3更改为要跳过的行数,包括匹配行。 例如,跳过包含7的每一行及其前面的 4 行:

$ seq 20 | tac | awk '/7/{c=5} !(c&&c--)' | tac
1
2
8
9
10
11
12
18
19
20

请参阅 https://stackoverflow.com/a/17914105/1745001,了解如何在匹配行周围打印您喜欢的任何行。

以您的示例为例:

$ tac file | awk '/[acgt]{3}cc[acgt][acgt]{3}/{c=3} !(c&&c--)' | tac
Sequence: MG719312_IGHV1-8*03_Homosapiens_F_V-REGION_127..422_296nt_1_____296+0=296___     from: 1   to: 296
  Start     End  Strand Pattern                 Mismatch Sequence
    217     225       + pattern:AA[CT]NNN[AT]CN        . aacacctcc

现在,您可能需要为数据考虑一些事项:

$ cat tst.awk
++lineNr == 1 {
    delete fldNr2tag
    delete tagNr2tag
    delete tag2val
    numTags = 0
    for (i=1; i<=NF; i+=2) {
        sub(/:.*/,"",$i)
        tag = $i (i>1 ? "" : 1) # to distinguish the 2 "Sequence" tags
        val = $(i+1)
        tagNr2tag[++numTags] = tag
        tag2val[tag] = val
    }
}
lineNr == 2 {
    for (i=1; i<=NF; i++) {
        tag = $i
        fldNr2tag[i] = tag
    }
}
lineNr == 3 {
    for (i=1; i<=NF; i++) {
        tag = fldNr2tag[i]
        val = $i
        tagNr2tag[++numTags] = tag
        tag2val[tag] = val
    }
    prt()
    lineNr = 0
}
function prt(   tagNr, tag, val) {
    for (tagNr=1; tagNr<=numTags; tagNr++) {
        tag = tagNr2tag[tagNr]
        val = tag2val[tag]
        printf "tag2val[%s] = <%s>n", tag, val
    }
    print "----"
}

.

$ awk -f tst.awk file
tag2val[Sequence1] = <MG719312_IGHV1-8*03_Homosapiens_F_V-REGION_127..422_296nt_1_____296+0=296___>
tag2val[from] = <1>
tag2val[to] = <296>
tag2val[Start] = <217>
tag2val[End] = <225>
tag2val[Strand] = <+>
tag2val[Pattern] = <pattern:AA[CT]NNN[AT]CN>
tag2val[Mismatch] = <.>
tag2val[Sequence] = <aacacctcc>
----
tag2val[Sequence1] = <M99648_IGHV2-26*01_Homosapiens_F_V-REGION_164..464_301nt_1_____301+0=301___>
tag2val[from] = <1>
tag2val[to] = <301>
tag2val[Start] = <176>
tag2val[End] = <184>
tag2val[Strand] = <+>
tag2val[Pattern] = <pattern:AA[CT]NNN[AT]CN>
tag2val[Mismatch] = <.>
tag2val[Sequence] = <aatcctaca>
----

请注意,通过上述内容,您可以按其名称访问每个值,从而从比较或其他计算中删除不精确和/或错误的匹配,并且您可以选择特定字段以您喜欢的任何顺序打印,只需使用字段名称,例如 print tag2val["Sequence"], tag2val["Pattern"] .因此,您可以简单地将数据转换为CSV,以便导入Excel或转换为HTML或JSON,或者对其进行其他任何操作。

查看示例文件,它似乎具有面向记录的结构,因此我会非常谨慎地尝试使用面向行的工具(如 grepsed(来操作它。正如评论中指出的那样,sed中的解决方案已经存在类似的问题,但脚本并不漂亮,维护或扩展将是一场噩梦。

我很想写一个简短的Perl或Python脚本来将文件解析为记录,然后处理记录。我不知道文件格式的细节,但像下面这样的东西可能是一个好的开始,并产生你想要的输出。

#!/usr/bin/perl -w
use strict;
my $line = <>;
unless (defined($line) && $line =~ /^Sequence/) {
    die "expected line to start with Sequence";
}
while (defined($line)) {
    my $record = $line;
    $line = <>;
    while (defined($line) && $line !~ /^Sequence/) {
        $record .= $line;
        $line = <>;
    }
    print $record unless $record =~ /[acgt]{3}cc[acgt][acgt]{3}/;
}

最新更新