关于正则表达式:除了模式及其下n行外,我该如何复制所有内容?

How can I grep everything except the pattern and its next n lines?

我有一个文件:

names.dat:

1
2
AAAA
BBBB

text.dat:

1
2
3
4
5
6
7
8
9
10
11
12
AAAA
CTGCTTCGTCA
12127567612
BBBB
TCGACTACTAG
12331276318
CCCC
TCATCATACAT
23612763812
DDDD
GCTATCGCATC
23767263723

我想做的是(仅使用shell命令)从text.dat中排除那些也出现在name.dat中的行,以及(最重要的是)在公共行之后加三行。

所以基本上输出应该像这样:

1
2
3
4
5
6
CCCC
TCATCATACAT
23612763812
DDDD
GCTATCGCATC
23767263723

您可以使用awk执行此操作:

1
awk 'NR==FNR {a[$0]; next} $0 in a {i=0} ++i>3' names.dat text.dat

NR==FNR表示总记录号等于当前文件的记录号(仅对第一个文件适用)。使用names.dat行设置数组a中的键。 next跳过输入的下一行,而忽略单行代码中的任何其他命令。每当text.dat中的行与a的元素匹配时,计数器i就会重置为0。仅当i大于3时才打印行。

进行测试:

1
2
3
4
5
6
7
$ awk 'NR==FNR {a[$0]; next} $0 in a {i=0} ++i>3' names.dat text.dat
CCCC
TCATCATACAT
23612763812
DDDD
GCTATCGCATC
23767263723

如果text.dat中的每一行都是唯一的:

1
grep -Fxvf <(grep -f names.dat -A 2 text.dat | grep -v '^--' ) text.dat

输出:

1
2
3
4
5
6
CCCC
TCATCATACAT
23612763812
DDDD
GCTATCGCATC
23767263723


您可以使用grep命令执行此操作。

1
grep -v"`grep -f name.dat -A 2 text.dat`" text.dat

输出如下。

1
2
3
4
5
6
CCCC
TCATCATACAT
23612763812
DDDD
GCTATCGCATC
23767263723

备注:
text.dat必须在" AAAA "和" BBBB "以及" BBBB "和" CCCC "之间有两行,因为" 2 "是魔术数字...


如果:

  • 文件中没有选项卡,并且

  • 这些模式中没有正则表达式元字符,然后:

    1
    2
    3
    4
    5
    paste -sd'\\t\\t\
    '
    text.dat |
    grep -v -f <(mapfile -t a <names.dat;printf '^%s\\t\
    '
    "${a[@]}") |
    tr \\\\t \\\
  • 具有的优势是,如果需要的话,它可以真正地将三行的行进行比较。


    正则表达式在反转下关闭。这意味着,如果您可以使用正则表达式匹配x,则可以使用正则表达式匹配除x之外的所有内容。

    (AAAA\
    |BBBB\
    )
    是您的模式,并且您想将该模式与接下来的三行匹配。 (与您的问题相反。)请注意,\
    表示换行符。

    (AAAA\
    |BBBB\
    )([^\
    ]*\
    ){3}
    会得到这个。 [^\
    ]
    的意思是"除换行符外的所有内容"。该表达式找到您的模式,外加三行完整的代码。 (由于grep不支持大括号表示法,因此应使用egrep。)

    传递参数-v来反转表达式。