删除与某个模式匹配的连续行及其后面的 3 行

删除与某个模式匹配的连续行及其后面的 3 行

我有一个包含以下内容的文件:

dn : Does not matter
 uid=321 456 678
foo=/234
bar=/456
git=/543

 uid=321 456 678
 uid=678 987 098
foo=/234
bar=/456
git=/543

dn : Does it matter
 uid=321 456 678
foo=/543
bar=/423
git=/501

我想删除任何uid=连续出现的情况以及其后的 3 行,以便预期输出为:

 dn : Does not matter
 uid=321 456 678
foo=/234
bar=/456
git=/543

dn : Does it matter
 uid=321 456 678
foo=/543
bar=/423
git=/501

我已经在两台服务器上尝试过了。不幸的是,我无法访问我尝试过大部分尝试的一台服务器。因此,在第二台服务器上,我尝试了以下各种变体,但我无法获得所需的结果。

sed '/^ uid=/N;{/\n uid= & & \n ^change type & & \n ^replace/d;}' pattern2.txt
awk '{/pat/?f++:f=0} f==2 {f--;}; 1' < pattern2.txt
sed '/^ uid=/N;{/\n uid=/D;}' pattern1.txt
awk '{/ uid=/?f++:f=0} f==2' pattern1.txt

答案1

使用sed

$ sed -f script.sed file
dn : Does not matter
 uid=321 456 678
foo=/234
bar=/456
git=/543

dn : Does it matter
 uid=321 456 678
foo=/543
bar=/423
git=/501

...script.sed哪里

H              # Append a newline and the current line to the hold space
/^$/bout       # Empty line: branch to ':out'
$bout          # Last line: branch to ':out'
d              # Delete line, start again from the top
:out
x              # Swap in the data from the hold space
/uid.*uid/d    # Delete the data if it contains two "uid"
s/\n//         # Remove the first embedded newline
               # (implicit print)

这会收集“保留空间”(中的通用缓冲区sed)中的读取行,并且当它遇到空行或输入末尾时,保留空间包含原始文件中的“块”之一。如果这样的块包含字符串 的两个实例uid,则将其丢弃,否则将其输出。

答案2

我觉得awk这可以简化,但目前还不能

awk '/uid=/ && p~/uid=/{c=4; next}
     !(c && c--) && NR>1{print p} {p=$0}
     END{if(c==0)print p}' ip.txt
  • 默认情况下,awk 中未初始化的变量将为空字符串或 0,具体取决于上下文
  • /uid=/ && p~/uid=/如果当前行和上一行包含uid=
    • c=4; next使用要跳过的行数进行初始化c(由于我最终的逻辑而加 1)。另外,跳过其余代码
  • !(c && c--) && NR>1{print p}如果当前行号大于 1 并且 if ,则打印上一行c==0。如果c大于0,则继续递减,直到c==0
  • {p=$0}保存上一行以供进一步使用
  • END{if(c==0)print p}打印最后一行如果c==0

相关内容