简体   繁体   English

使用 sed 在最后一次出现模式后删除特定行

[英]Using sed to delete specific lines after LAST occurrence of pattern

I have a file that looks like:我有一个看起来像的文件:

this name
this age

Remove these lines and space above.
Remove here too and space below

Keep everything below here. 

I don't want to hardcode 2 as the number of lines containing "this" can change.我不想硬编码 2,因为包含“this”的行数可以改变。 How can I delete 4 lines after the last occurrence of the string.如何在最后一次出现字符串后删除 4 行。 I am trying sed -e '/this: /{n;N;N;N;N;d}' but it is deleting after the first occurrence of the string.我正在尝试sed -e '/this: /{n;N;N;N;N;d}'但它在第一次出现字符串后被删除。

Could you please try following.请您尝试以下操作。

awk '
FNR==NR{
  if($0~/this/){
    line=FNR
  }
  next
}
FNR<=line || FNR>(line+4)
'  Input_file Input_file

Output will be as follows with shown samples. Output 将如下所示样品。

this: name
this: age
Keep everything below here.

You can also use this minor change to make your original sed command work.您还可以使用此微小更改来使您的原始 sed 命令正常工作。

sed '/^this:/ { :k ; n ; // b k ; N ; N ; N ; d }' input_file

It uses a loop which prints the current line and reads the next one ( n ) while it keeps matching the regex (the empty regex // recalls the latest one evaluated, ie /^this:/ , and the command bk goes back to the label k on a match).它使用一个循环打印当前行并读取下一行( n ),同时它保持匹配正则表达式(空正则表达式//调用最新评估的行,即/^this:/ ,并且命令bk回到label k上一场比赛)。 Then you can append the next 3 lines and delete the whole pattern space as you did.然后你可以 append 接下来的 3 行并像你一样删除整个模式空间。

Another possibility, more concise, using GNU sed could be this.使用 GNU sed 的另一种更简洁的可能性可能是这样。

sed '/^this:/ b ; /^/,$ { //,+3 d }' input_file

This one prints any line beginning with this: ( b without label goes directly to the next line cycle after the default print action).这个打印任何this:没有 label 的b在默认打印操作后直接进入下一行循环)。

On the first line not matching this: , two nested ranges are triggered.this:不匹配的第一行中,触发了两个嵌套范围。 The outer range is "one-shot".外部范围是“一次性”。 It is triggered right away due to /^/ which matches any line then it stays triggered up to the last line ( $ ).由于/^/与任何行匹配,它会立即触发,然后它会一直触发到最后一行( $ )。 The inner range is a "toggle" range.内部范围是“切换”范围。 It is also triggered right away because // recalls /^/ on this line (and only on this line, hence the one-shot outer range) then it stays trigerred for 3 additional lines (the end address +3 is a GNU extension).它也被立即触发,因为//在这一行召回/^/ (并且仅在这一行,因此单次外部范围)然后它保持触发 3 个额外的行(结束地址+3是 GNU 扩展) . After that, /^/ is no longer evaluated so the inner range cannot trigger again because // recalls /^this:/ (which is short cut early).之后, /^/不再被评估,因此内部范围不能再次触发,因为//召回/^this:/ (这是早期的捷径)。

This might work for you (GNU sed):这可能对您有用(GNU sed):

sed -E ':a;/this/n;//ba;$!N;$!ba;s/^([^\n]*\n?){4}//;/./!d' file 

If the pattern space (PS) contains this , print the PS and fetch the next line.如果模式空间 (PS) 包含this ,则打印 PS 并获取下一行。

If the following line contains this repeat.如果以下行包含this重复。

If the current line is not the last line, append the next line and repeat.如果当前行不是最后一行,则 append 下一行并重复。

Otherwise, remove the first four lines of the PS and print the remainder.否则,删除 PS 的前四行并打印剩余部分。

Unless the PS is empty in which case delete the PS entirely.除非 PS 为空,在这种情况下完全删除 PS。

NB This only reads the file once.注意这只会读取一次文件。 Also the OP says OP还说

How can I delete 4 lines after the last occurrence of the string如何在最后一次出现字符串后删除 4 行

However the example would seem to expect 5 lines to be deleted.但是,该示例似乎期望删除 5 行。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM