sed-根据模式删除上一行和当前行

sed-根据模式删除上一行和当前行,sed,Sed,我想根据下一行的模式匹配删除上一行和当前行 这是我的sample.txt This is test line 11 This is test line 999 This is test line 12 This is test line 13 This is test line 16 This is test line 999 This is test line 17 This is test line 18 我想匹配模式999并删除其本身和前一行 我正在尝试此命令,但没有得到任何输出 sed

我想根据下一行的模式匹配删除上一行和当前行

这是我的sample.txt

This is test line 11
This is test line 999
This is test line 12
This is test line 13
This is test line 16
This is test line 999
This is test line 17
This is test line 18
我想匹配模式999并删除其本身和前一行

我正在尝试此命令,但没有得到任何输出

sed -Ene ':a;N;/999/{d;}; ba; P' sample.txt

如果可以的话,请你试试下面的

或者,如果您有偶数行,并且希望打印最后一个奇偶

awk 'prev && $NF!=999{print prev ORS FNR,$0;prev="";next} $NF==999{prev=""} $NF!=999{prev=FNR FS $0} END{if(prev){print prev}}'  Input_file

如果可以的话,请你试试下面的

或者,如果您有偶数行,并且希望打印最后一个奇偶

awk 'prev && $NF!=999{print prev ORS FNR,$0;prev="";next} $NF==999{prev=""} $NF!=999{prev=FNR FS $0} END{if(prev){print prev}}'  Input_file
对于sed1解决方案,它处理前2行或999的连续行中的所有边缘情况999:

塞德 1{ /第1行需要999/d特殊情况。如果包含999,则删除。 } $!N追加下一行。$!N在EOF停止退出,不打印。 /999/d如果模式空间包含999,则d&开始下一个循环。 P如果我们到了这里,就没有999了。打印到第一个换行符。 D删除到第一个换行符。 "档案" 输出:

这是测试线12 这是13号试车线 这是17号试车线 这是18号试车线 1在BSD Mac OS X和GNU sed上测试。

针对sed1解决方案,该解决方案处理前2行或连续999行中的所有边缘情况999:

塞德 1{ /第1行需要999/d特殊情况。如果包含999,则删除。 } $!N追加下一行。$!N在EOF停止退出,不打印。 /999/d如果模式空间包含999,则d&开始下一个循环。 P如果我们到了这里,就没有999了。打印到第一个换行符。 D删除到第一个换行符。 "档案" 输出:

这是测试线12 这是13号试车线 这是17号试车线 这是18号试车线
1在BSD Mac OS X和GNU sed上进行了测试。

这可能适用于GNU sed:

sed 'N;/\n.*999/d;P;D' file
在整个文件长度上打开一个两行的运行窗口

如果窗口的第二行包含999,则删除这两行

否则,打印窗口的第一行,删除第一行并重复

第1行、第2行或更多包含999的连续行的替代解决方案:


这可能适用于GNU sed:

sed 'N;/\n.*999/d;P;D' file
在整个文件长度上打开一个两行的运行窗口

如果窗口的第二行包含999,则删除这两行

否则,打印窗口的第一行,删除第一行并重复

第1行、第2行或更多包含999的连续行的替代解决方案:

在gnu-sed上试用

 sed -Ez 's/[^\n]*\n[^\n]*999\n//g' sample.txt
在gnu-sed上试用

 sed -Ez 's/[^\n]*\n[^\n]*999\n//g' sample.txt

更全面的样本输入包括:

$ cat file
This is test line 999
This is test line 11
This is test line 999
This is test line 12
This is test line 13
This is test line 999
This is test line 999
This is test line 999
This is test line 14
This is test line 15
This is test line 16
This is test line 999
This is test line 17
This is test line 18
试试这个:

$ cat tst.awk
$NF == 999 {
    prev = ""
    next
}
{
    printf "%s", prev
    prev = $0 ORS
}
END {
    printf "%s", prev
}

$ awk -f tst.awk file
This is test line 12
This is test line 14
This is test line 15
This is test line 17
This is test line 18
或者如果你喜欢简洁而不是清晰:

$ awk '$NF==999{p="";next} {printf "%s",p; p=$0 ORS} END{printf "%s",p}' file
This is test line 999
This is test line 11
This is test line 999
This is test line 12
This is test line 13
This is test line 999
This is test line 999
This is test line 999
This is test line 14
This is test line 15
This is test line 16
This is test line 999
This is test line 17
This is test line 18

请注意,即使最后一个字段以外的行的某些其他部分包含999,或者如果最后一个字段为9999而不是目标999,也不需要在脚本中多次写入/测试999,例如,行中的第三个字段(而不是最后一个字段)可以将$NF更改为$3=,如果要测试整行的regexp,只需将$NF==999更改为/999/,即使目标字符串包含regexp元字符,它也可以工作,它将在任何UNIX设备上的任何shell中的任何awk中工作。

更全面的示例输入:

$ cat file
This is test line 999
This is test line 11
This is test line 999
This is test line 12
This is test line 13
This is test line 999
This is test line 999
This is test line 999
This is test line 14
This is test line 15
This is test line 16
This is test line 999
This is test line 17
This is test line 18
试试这个:

$ cat tst.awk
$NF == 999 {
    prev = ""
    next
}
{
    printf "%s", prev
    prev = $0 ORS
}
END {
    printf "%s", prev
}

$ awk -f tst.awk file
This is test line 12
This is test line 14
This is test line 15
This is test line 17
This is test line 18
或者如果你喜欢简洁而不是清晰:

$ awk '$NF==999{p="";next} {printf "%s",p; p=$0 ORS} END{printf "%s",p}' file
This is test line 999
This is test line 11
This is test line 999
This is test line 12
This is test line 13
This is test line 999
This is test line 999
This is test line 999
This is test line 14
This is test line 15
This is test line 16
This is test line 999
This is test line 17
This is test line 18

请注意,即使最后一个字段以外的行的某些其他部分包含999,或者如果最后一个字段为9999而不是目标999,也不需要在脚本中多次写入/测试999,例如,行中的第三个字段(而不是最后一个字段)可以将$NF更改为$3=,如果要测试整行的regexp,只需将$NF==999更改为/999/,即使目标字符串包含regexp元字符,它也可以工作,它可以在任何UNIX设备上的任何shell中的任何awk中工作。

我只想使用sed我想使用sed OnlyTanks为此,如果我需要使用flow,请告诉我sed的错误在哪里control@rgd,你的剧本是:a;N/999/天;文学士;P.N将下一行追加到图案空间。然后,如果/999/完全删除模式空间并开始下一个循环。如果不是/999/,请转到a。因此,您的P命令无法访问,这就是您无法获得输出的原因。谢谢,我如何修复我的代码,我的意思是我需要在代码中放置P?谢谢,如果我需要使用flow,您能告诉我sed的错误在哪里吗control@rgd,你的剧本是:a;N/999/天;文学士;P.N将下一行追加到图案空间。然后,如果/999/完全删除模式空间并开始下一个循环。如果不是/999/,请转到a。因此,您的P命令无法访问,这就是您无法获得输出的原因。谢谢,我如何修复我的代码,我的意思是我需要在代码中的何处放置P?如果999位于第一行,此命令将无法工作。我用1号线的一个特例解决了这个问题。

不确定是否有更好的方法。@AlexHarvey OP没有指定当第一行包含999时应该发生什么,也没有指定当两行或更多行包含999时应该发生什么。但是,请参见编辑。我认为\n.*在第一个正则表达式中不需要?@AlexHarvey我认为这是case仅在第二行中读取999。几个问题1。当我们从标签B到A时,下一行要读取的是我们最初离开的那一行,还是从内部标签B结束的那一行开始?我想知道当n读取包含999的连续行,然后返回到标签A时,NIt分支的内容会是什么,就像goto语句一样,立即无条件地。如果999在第一行,这个分支将不起作用。我用1号线的一个特例解决了这个问题。不确定是否有更好的方法。@AlexHarvey OP没有指定当第一行包含999时应该发生什么,也没有指定当两行或更多行包含999时应该发生什么。但是,请参见编辑。我认为\n.*在第一个正则表达式中不需要?@AlexHarvey我认为这是case仅在第二行中读取999。几个问题1。当我们从标签B到A时,下一行要读取的是我们最初离开的那一行,还是从内部标签B结束的那一行开始?我想知道当n读取包含999的连续行,然后返回到标签A时,NIt分支的内容会是什么,就像goto语句一样,是对单个字符串执行s/old/new/的最佳工具。这不是你在这里要做的,因此sed不是工作的最佳工具,那么,如果可以使用其他工具更清晰、更简单、更可靠、更便携和/或更高效地完成工作,为什么要使用sed呢?您应该包括一个案例,其中999显示为输入的第一行,它显示在3个连续的行上,以显示您希望如何处理这些内容,并为我们提供一些东西来充分测试潜在的解决方案。我认为这是一个很好的问题@rgd.sed是对单个字符串执行s/old/new/操作的最佳工具。这不是你在这里要做的,因此sed不是工作的最佳工具,那么,如果可以使用其他工具更清晰、更简单、更可靠、更便携和/或更高效地完成工作,为什么要使用sed呢?您应该包括一个案例,其中999显示为输入的第一行,它显示在3个连续的行上,以显示您希望如何处理这些内容,并为我们提供一些东西来充分测试潜在的解决方案。我认为这是一个伟大的问题@rgd。它并没有比我的sed解决方案简单多少,是吗?我接受可移植性的观点。否则,与模式空间中附加的magic N不同,您有一个magic prev=$0 ORS,它的作用与sed的N相同。我不必为代码添加注释以使其清晰易懂,变量赋值也没有什么神奇之处。另外,与seds N不同的是,如果我们想增强到删除,比如,在目标行之前10行而不是1行,我不需要写10次语句来保存10行,我只需要让prev成为一个10行数组,带有一个循环来打印它,如果OP希望能够使用在运行时指定的可变行数,这在awk中与静态值完全相同,但在1中不可能做到关键是awk脚本有好处,而sed脚本没有好处。使用awk:需要打印已删除行数stderr吗?不重要的需要测试999是否在特定字段中?不重要的当输入字符串包含regexp元字符时,是否需要将其作为文本进行测试?不重要的还需要删除目标行之后的行吗?不重要的仅当前面的行包含其他字符串时才需要删除它们?不重要的等等等等。。使用awk if/当需求发生变化时,您通常只是在已有的基础上进行构建,而使用sed通常是不可能的或重写的。哦,拜托,awk只是python或C或任何其他基于algol的语言,具有较少的语言结构、六个关键字、隐式while read split循环以及围绕条件的隐式ifs{action}另一方面,blocks.sed在语法和语义上都有很大的不同。wrt 5行脚本的可维护性-您不只是以某种方式编写脚本以准备增强该脚本,而是以这种方式编写脚本,以便在下一个类似任务出现时,您可以以基本相同的方式编写下一个脚本,但使用较小的d必要时的区别。编写可维护脚本不应该是您在必要时决定要做的事情,而应该是您要做的事情,除非有迫切的需要,例如出于性能原因。无论如何,正如我在另一篇文章中所说,在我决定开始使用awk来处理文本之前,我花了10年的时间使用sed和shell这不仅仅是s/旧的/新的,听起来你才刚刚开始你自己的旅程,并且很高兴继续这样做——一切都很好。这并不比
我的sed解决方案是什么?我接受可移植性的观点。否则,与模式空间中附加的magic N不同,您有一个magic prev=$0 ORS,它的作用与sed的N相同。我不必为代码添加注释以使其清晰易懂,变量赋值也没有什么神奇之处。另外,与seds N不同的是,如果我们想增强到删除,比如,在目标行之前10行而不是1行,我不需要写10次语句来保存10行,我只需要让prev成为一个10行数组,带有一个循环来打印它,如果OP希望能够使用在运行时指定的可变行数,这在awk中与静态值完全相同,但在1中不可能做到关键是awk脚本有好处,而sed脚本没有好处。使用awk:需要打印已删除行数stderr吗?不重要的需要测试999是否在特定字段中?不重要的当输入字符串包含regexp元字符时,是否需要将其作为文本进行测试?不重要的还需要删除目标行之后的行吗?不重要的仅当前面的行包含其他字符串时才需要删除它们?不重要的等等等等。。使用awk if/当需求发生变化时,您通常只是在已有的基础上进行构建,而使用sed通常是不可能的或重写的。哦,拜托,awk只是python或C或任何其他基于algol的语言,具有较少的语言结构、六个关键字、隐式while read split循环以及围绕条件的隐式ifs{action}另一方面,blocks.sed在语法和语义上都有很大的不同。wrt 5行脚本的可维护性-您不只是以某种方式编写脚本以准备增强该脚本,而是以这种方式编写脚本,以便在下一个类似任务出现时,您可以以基本相同的方式编写下一个脚本,但使用较小的d必要时的区别。编写可维护脚本不应该是您在必要时决定要做的事情,而应该是您要做的事情,除非有迫切的需要,例如出于性能原因。无论如何,正如我在另一篇文章中所说,在我决定开始使用awk来处理文本之前,我花了10年的时间使用sed和shell这不仅仅是s/旧的/新的,听起来你刚刚开始了你自己的旅程,并且很高兴继续这样做——一切都很好。