对两种模式之间的线条逐渐进行Sed

时间:2013-12-26 16:44:40

标签: bash sed

以下是我的示例代码:

BEGIN
one
one
one one
one
END
filler filler filler filler
BEGIN
two two
two
two two
END
filler filler filler filler
BEGIN
three three three
three three
three
END

我想提取(包括)BEGINEND之间的界限。我有一个已经这样做的sed:

sed '/BEGIN/,/END/!d' file

但我想逐步提取模式空间。也就是说,我可以对上面的sed命令做什么才能输出第一个块?然后第二块?第三个?等...

(正如你们有些人猜的那样,我的最终目标是解析一个带有x509证书的文件并提取文件中每个证书的数据,而不仅仅是openssl默认执行的文件中的第一个证书。如果有的话是一个比上面更容易的选择,我都是耳朵。)

3 个答案:

答案 0 :(得分:2)

我不确定您是否可以轻松地在sed中执行此操作,但您可以在awk中执行此操作:

awk '/^BEGIN$/         { file = sprintf("file%d.out", ++i); }
     /^BEGIN$/,/^END$/ { print > file }' data

这会为第一个块生成file1.out,为第二个块生成file2.out等等。


  

你能解释一下awk的工作部分吗?

第一条规则行匹配包含BEGIN的行,并使用变量file中的计数器在变量i中生成文件名(预先递增,因此第一个文件为{ {1}})。

第二条规则行匹配从file1.outBEGIN的行范围,并使用END(又名print)重定向到变量{{1}指定的当前文件}}。因此每次都会写入相关文件。

  

另外,如何将其更改为将内容输出到stdout?我希望有一种方法可以指定一个“第N个”模式参数,我将从一个简单的for循环中提供,该循环运行的次数与发现模式“BEGIN”总数相同。

您可以使用一行来计算块并跳过除相关块之外的所有块,然后只打印相关块的数据。

print $0

file将shell变量awk -v N=$N '/^BEGIN$/ { if (++i != N) next; } /^BEGIN$/,/^END$/ { print }' data 转发给-v N=$N;第一行计数(使用$N部分,跳过除N th 之外的所有部分。第二行仅在第一行不跳过它时被触发,因此它打印出的内容N th 块。一些awk afficionados(他们在业余时间可能是APL程序员)会省略i块,但我认为它使代码更清晰谁必须维护代码。

答案 1 :(得分:0)

可以使用相反的方式。不打印默认值并仅打印图案之间的线

sed -n '/BEGIN/,/END/p' <file

答案 2 :(得分:0)

使用awk,仅导出第二条记录,无需遍历整个文件。您将在文件“file.out”中获得结果。您可以自己定义数字(n = 2)。

n=2
awk -v N=$n '/^BEGIN$/{++i}
     /^BEGIN$/,/^END$/ { if (i==N) {print > "file.out";quit}}'  file