如何使用sed提取并打印START与END标记间的文本块
问题描述
现有test.txt文件内容如下:
This is a text2 This is a text3 This is a text4 This is a text5 START This is a text1 END This is a text6 This is a text7 This is a text8 This is a text9
需求为打印START和END两个标记之间的文本块,前期尝试的两条sed命令均执行失败,同时需要确认sed是否为该场景的最优工具,若存在更适配的工具需给出对应使用示例。
前期尝试的错误命令如下:
cat $(test.txt) | sed -n -e '{/START/=},{/END/=}p':预期通过{/START/=}、{/END/=}块返回两个标记的行号,以此确定打印范围cat $(test.txt) | sed -n -e '$(sed -n -e "/START/="),$(sed -n -e "/END/=")p':预期通过命令替换嵌入子sed命令获取标记行号,作为打印范围参数
命令错误原因说明
- 语法基础错误:
$(test.txt)是shell命令替换语法,会尝试将test.txt作为可执行命令运行,而非读取文件内容,cat读取文件直接跟文件名即可,不需要套$();另外sed本身支持直接传入文件路径参数,不需要额外通过cat管道传输入,属于冗余写法。 - sed逻辑错误:sed的地址范围直接支持正则匹配,不需要提前计算行号;
/START/=是匹配到START行时打印行号的动作,不会给范围表达式返回行号;单引号包裹的内容不会被shell解析,第二条命令里的$()写在单引号内部,根本不会执行子命令获取行号。
正确sed实现
sed原生支持正则区间匹配,不需要提前计算行号:
- 打印包含START、END标记在内的整个区间内容:
sed -n '/START/,/END/p' test.txt
- 仅打印两个标记中间的内容,排除START、END标记行本身:
sed -n '/START/,/END/{//!p}' test.txt
针对给出的test.txt文件,执行后输出结果为:
This is a text1
其他适配工具示例
sed可以完成该需求,但如果涉及更复杂的区间内文本处理,awk的逻辑可读性更高、更不容易写错:
- 仅提取标记中间内容,排除标记行:
awk '/START/{flag=1;next} /END/{flag=0} flag' test.txt
逻辑说明:匹配到START行时将打印标记设为1,跳过当前START行;匹配到END行时将打印标记设为0;标记为1时自动打印当前行,逻辑直观,不需要记忆sed的特殊语法。
内容的提问来源于stack exchange,提问作者TornaxO7
相关产品推荐
相关产品推荐

