删除具有模式匹配的行和下一行

ken*_*use 23 grep sed awk text-processing

如果匹配模式,我试图从文件中删除模式匹配的所有实例。如果匹配,则删除具有匹配模式的(完整)行和下一行。

下一行总是出现在与模式匹配的行之后,但此外它还会出现在文件的其他区域。

我正在使用 grep 并按预期删除文件中所有出现的下一行。

有没有一种方法可以删除下一行,当且仅当它在模式匹配的行之后?

Mic*_*mer 26

您可以sedNd命令和{}块一起使用

sed -e '/pattern here/ { N; d; }'
Run Code Online (Sandbox Code Playgroud)

对于匹配的每一行,将执行 中pattern here的代码{}N将下一行也带入模式空间,然后d在移动到下一行之前删除整个内容。这适用于任何兼容 POSIX 的sed.


mik*_*erv 5

sed如果您使用N,大多数s 不会打印最后一行$。但是 GNUsed会。所以如果你想删除的模式在最后一行,你N就会打印出来。有时最好保持缓冲区已满 - 例如,除了不想打印的行,始终保留 2 行。你可能会这样做:

seq 10 | sed -n 'x;/7/!g;//!p'
Run Code Online (Sandbox Code Playgroud)

这是一个带有seqas 输入的示例。在每一行上,它交换保持空间和模式空间。如果最后保留的行与 a 不匹配7 (在这种情况下),它将用当前行覆盖保留空间。然后它再次检查它刚刚引入的行 - 当前行 - 也与 不匹配7,否则不会打印它。所以在每一行它检查前一行和当前行。

1
2
3
4
5
6
9
10
Run Code Online (Sandbox Code Playgroud)

如果您的模式确实落在最后一行:

seq 10 | sed -n 'x;/10/!g;//!p' 

1
2
3
4
5
6
7
8
9
Run Code Online (Sandbox Code Playgroud)

另一个例子,希望更清楚地展示它会和不会打印什么:

sed -n 'x;/match/!g;//!p
' <<\DATA
    match 
    match 
    1not 
    2not 
    3not 
    4not 
    5not 
    match 
    6not 
    match                                                              
DATA
Run Code Online (Sandbox Code Playgroud)

输出

2not
3not
4not
5not
Run Code Online (Sandbox Code Playgroud)

  • 使用此 A 中的示例,这似乎是唯一正确处理边缘场景的示例。 (2认同)

Ken*_*ter 5

一个awk解决方案:

awk '/pattern/    { matched=1; next }
     1 == matched { matched = 0; next }
                  { print }' input-file
Run Code Online (Sandbox Code Playgroud)

第 1 行查找与模式匹配的行,设置一个标志,然后跳过该行。第 2 行在设置标志时跳过一行,但重置标志。第 3 行打印没有被其他两行之一跳过的行。

如果您愿意,可以在一行中输入:

awk '/pattern/{matched=1;next} 1==matched{matched=0;next} {print}' input-file
Run Code Online (Sandbox Code Playgroud)

这是一个变体,可让您控制要跳过的行数:

awk '/pattern/{skip=3;next} skip>0{--skip;next} {print}' input-file
Run Code Online (Sandbox Code Playgroud)

设置skip为应该跳过的行数(除了匹配的行)。