使用 GNU sed 提取可能由空行分隔的两个模式行之间的标头名称

使用 GNU sed 提取可能由空行分隔的两个模式行之间的标头名称

我有以下文件:

------

Introduction
----------
Optio eum enim ut. Et quia molestias eos. Doloribus laborum quia quae. Magnam cupiditate quis consectetur.

-----
Chapter1: Foo
-----

Odit beatae eius voluptas temporibus sint quia. Eos et tempora similique laboriosam optio consequatur quibusdam. Fugit suscipit cupiditate ea perspiciatis rem labore cum eos.

-----
Chapter bar


-----
Et consequatur quia quia et architecto et sunt. Perferendis qui deserunt qui est illo est sapiente ipsam. Fugiat vel amet magni in quam. Eligendi totam cum sapiente harum blanditiis minima

具有以下约束:

  • 标题符号-至少出现 5 个或更多字符。
  • -和标题之间可以有任意(但有限)数量的空行。

预期输出是:

Introduction
Chapter1: Foo
Chapter bar

我知道这可以通过使用来完成awk,但请不要建议这样做。我希望看到一个纯粹的 GNU sed 解决方案。

这是我到目前为止所尝试过的:

sed -n ':a; /-\+/{n; /^$/!{p; b a}}' input.txt

但该命令似乎不起作用。

答案1

这将打印至少包含一个字母或数字字符的行,只要它们位于标题内即可。

sed -n '/^-----/,/^-----/{/[[:alnum:]]/p;}' file

答案2

我提出这个解决方案:

$ sed -n '/\-\{5,\}/,/\-\{5,\}/p' file | sed '/\-\+\|^$/d'
Introduction
Chapter1: Foo
Chapter bar

  • '/\-\{5,\}/,/\-\{5,\}/p'选择之间的部分-(至少 5 个)。
  • '/\-\+\|^$/d'删除空白行或以-.

答案3

虽然您确实可以在sed其他工具中执行此操作会让事情变得更容易(IMO)1也可以工作。例如,在awk

$ awk '/-----/ && !a{a=1;next} /-----/ && a{a=0}a' file 

Introduction
Chapter1: Foo
Chapter bar


要摆脱空行,您可以这样做:

$ grep . file | awk '/-----/ && !a{a=1;next} /-----/ && a{a=0}a'
Introduction
Chapter1: Foo
Chapter bar

或者:

$ awk '!/./{next};/-----/ && !a{a=1;next} /-----/ && a{a=0}a' file 
Introduction
Chapter1: Foo
Chapter bar

这里的想法是,如果变量当前为 0 或未设置 ( a) ,并且当前行至少匹配 5 ,则将其设置为 。如果在设置为 1时找到另一行包含 5 的行,则将其重新设置为 。然后,我们打印所有设置了 的行(这就是 final所做的:如果计算结果为非 0,它将打印)。1!a-0-aaaa

这是以更容易理解的方式编写的相同内容:

awk '{ 
        if(!/./){ next } 
        if(/-----/ && !a){ a=1; next} 
        if(/-----/ && a){ a=0 } 
        if(a){ print }
    }' file

1卡西莫多的回答就更简单了!

答案4

您可以使用:

sed -n '/^-\+$/,/^-\+$/{/^-*$/!p}' input.txt

或者,您也可以使用sed -z

sed -Ez 's/[^-]*-+[\n]*([^\n]*\n)[\n]*-+[^-]*/\1/g' input.txt

没有-E

sed -z 's/[^-]*-\+[\n]*\([^\n]*\n\)[\n]*-\+[^-]*/\1/g' input.txt

注意:虽然这对于您的示例来说效果很好,但如果-出现在文本中的某个位置,则可能会出现问题。但我认为,你可以详细说明这一点。

相关内容