假设我有一个格式为的文件:
(lots of sections...)
SECTION foo
keyA=valA
...
ENDSECTION
(lots of sections...)
我可以使用 sed 提取该部分sed -nE /^SECTION foo$/,/^ENDSECTION$/p
。当格式更改为:时出现我的问题:
(lots of sections...)
SECTION
keyA=valA
id=foo
...
ENDSECTION
(lots of sections...)
有没有一种方法可以通过使用常用工具(grep、sed、awk、perl、bash)来获取该部分?
答案1
这在某种程度上取决于您的文档的“格式良好”程度。如果您确定每个SECTION
都有匹配的ENDSECTION
,那么下面的awk
代码应该可以工作,尽管我不会将其称为“单行代码”(而且我一开始就不确定这是否可能)。
awk -v pat='id=foo' '/^SECTION/{n=f=0; delete buf;} \
{buf[++n]=$0; if (index($0,pat)) f=1} \
/^ENDSECTION/ {if (f) for (i=1;i<=n;i++) print buf[i]}' input.txt
- 搜索模式将是您指定的任何内容
pat
(但在当前形式中,它仅执行固定字符串搜索,而不是基于正则表达式的搜索)。 SECTION
当找到以(或任何关键字)开头的行时,标志f
(表示“找到”)和行计数器n
将初始化为零。另外,由于我们需要缓冲整个部分,因为只有在该部分完成后才能决定是否打印,因此我们清除了一个缓冲区变量buf
。- 对于任何行(包括本例中的空行),行计数器
n
都会增加,并将该行添加到数组变量 中buf
。如果在线上找到该模式,则该f
标志设置为1
。 - 如果
ENDSECTION
在行首找到关键字,并且标志f
为1
,则逐行打印缓冲区以输出相关部分。
如果您可以保证所有部分都用空行分隔,这个答案可以为您指明如何使用更少的代码来完成此操作的正确方向,但如果不能保证这一点,则“段落模式”方法awk
将不起作用。
另请注意,此建议是完成任务所需的最低限度的建议;如果您想跳过空行或满足其他健全性检查要求,代码很快就会变得相当长。