【发布时间】:2016-02-27 03:38:43
【问题描述】:
假设我有一个文件:
Line 1
Line 2
Start Line 3
Line 4
Line 5
Line 6
End Line 7
Line 8
Line 9
Start Line 10
Line 11
End Line 12
Line 13
Start line 14
Line 15
只有在找到 /Start/ 和 /End/ 时,我才想使用 sed 在模式之间打印。
sed -n '/Start/,/End/p' 如果您知道两个标记都在那里并且按照预期的顺序工作,那么它会按预期工作,但如果End 出现故障或不存在,它只会从Start 打印到文件末尾。 (即在示例中打印第 14 行和第 15 行)
我试过了:
sed -n '/Start/,/End/{H;}; /End/{x; p;}' file
打印:
# blank line here...
Start Line 3
Line 4
Line 5
Line 6
End Line 7
End Line 7
Start Line 10
Line 11
End Line 12
这很接近,但有两个问题:
- 不需要的前导空白行
- 第 7 行结束打印两次
我希望得到类似的结果
$ awk '/Start/{x=1} x{buf=buf$0"\n"} /End/{print buf; buf=""; x=0}' file
Start Line 3
Line 4
Line 5
Line 6
End Line 7
Start Line 10
Line 11
End Line 12
(块之间不需要空行...)
【问题讨论】:
-
块内是否允许另一个“起始行”? (比如第5行是起始行,你要3-7块还是5-7块?)
-
@CasimiretHippolyte:好问题。不,它不需要处理重叠或嵌套的
/Start/块。只需处理(通过不打印)缺少/End/ -
所以答案是第 5-7 块?
-
只是好奇 - 因为这可以在 awk 中简单、稳健且可移植地完成,而且您已经知道如何在 awk 中完成,为什么还要寻找 sed 解决方案?
-
GNU awk 具有捕获组,但它们只是一种方便,您可以使用 POSIX awk 获得必要的行为,它可能需要您编写更多代码。在使用 sed 30 多年和使用 awk 20 多年之后,我的建议是您使用 sed 进行单行的简单替换,而使用 awk 进行其他所有操作。即使简单内容的 awk 代码最终会稍微不那么简短,但至少您正在学习如何在需要处理复杂内容时使用 awk!如果您愿意发布它,我很想看看您在新问题中提到的更完整的示例。