Sed范围并删除最后一个匹配行

时间:2018-06-07 16:41:25

标签: bash shell sed

我有这些数据:

One
  two
  three
Four
  five
  six
Seven
  eight

这个命令:

sed -n '/^Four$/,/^[^[:blank:]]/p'

我得到以下输出:

Four
  five
  six
Seven

如何更改此sed表达式与输出的最后一行不匹配?所以理想的输出应该是:

Four
  five
  six

我尝试了很多涉及感叹号的事情,但还没有成功地接近这个问题。

6 个答案:

答案 0 :(得分:7)

使用“do..while()”循环:

sed -n '/^Four$/{:a;p;n;/^[[:blank:]]/ba}'

细节:

/^Four$/ {
    :a         # define the label "a"
    p          # print the pattern-space
    n          # load the next line in the pattern space
    /^[[:blank:]]/ba # if the pattern succeeds, go to label "a"
}

答案 1 :(得分:4)

你可以管道到另一个sed并跳过最后一行:

sed -n '/^Four$/,/^[^[:blank:]]/p' file | sed '$d'

Four
  five
  six

或者您可以使用:

sed -n '/^Four$/,/^[^[:blank:]]/{/^Four$/p; /^[^[:blank:]]/!p;}' file

答案 2 :(得分:2)

您使用了错误的工具。 sed是做s / old / new,就是这样。只需使用awk:

$ awk '/^[^[:blank:]]/{f=/^Four$/} f' file
Four
  five
  six

工作原理:每次找到一个不以空格开头的行(/^[^[:blank:]]/)时,它会设置一个标记f(对于"找到")如果该行以Four开头,则为0,否则为{f=/^Four$/)。每当f非零时被解释为真实条件,因此调用awks默认行为,即打印当前行。因此,当它遇到以Four开头的块时,它会打印该块中的每一行,因为f是1 / true,而对于其他每个块,它都不打印,因为f是0 / false。 / p>

答案 3 :(得分:1)

关注awk可能会对您有所帮助。

awk '!/^ /{flag=""} /Four/{flag=1} flag'   Input_file

输出如下。

Four
  five
  six

如果您需要将输出保存到Input_file本身,请将> temp_file && mv temp_file Input_file附加到上面的代码中。

答案 4 :(得分:0)

grep -Pzo '\n\KFour\n(\s.+\n)+' input.txt

<强>输出

Four
  five
  six

答案 5 :(得分:0)

这可能适合你(GNU sed):

sed '/^Four/{:a;n;/^\s/ba};d' file

如果该行以Four开头,则打印它以及以空格开头的任何后续行。

另一种方式:

sed '/^\S/h;G;/^Four/MP;d' file

如果一行以非空格开头,请将其复制到保留空间(HS)。将HS附加到每一行,如果任一行以Four开头,则打印第一行并删除其余行。这将删除除Four开头的部分以外的所有行。