sed一次处理多行



文件中有两行,如下所示:

#foo:
#   bar=<need replacement>

当第一行以foo开头,第二行包含bar并替换<>之间的文本时,我想删除#,如果它存在(取消行注释)。

我可以在使用sed的N;P;D周期的一次传递中做到这一点吗?或者还有其他更简单的方法吗?

这可能适合您(GNU sed):

sed -E '/^#?foo/{N;/n.*bar/{s/^#//mg;s/(n.*<).*(>.*)/1replace2/};P;D}' file

如果当前行以foo注释或未注释开始,则:

  • 添加以下行

  • 如果下面一行包含单词bar,则:

    • 删除任意两行开头的#
    • 将第二行<>之间的字符替换为replace
  • 打印/删除第一行并重复。

注意:这允许处理前导foo,然后是另一个前导foo,然后是bar

使用带有标准N;…;P;D;循环和基本正则表达式的POSIX sed(BRE):

sed -e '$!N' -e '/^#(foo:n)#([[:blank:]]*bar)=.*/ s//12=newvalue/' -e P -e D < file

这可能是可以做到的,但我会使用不同的工具。Awk怎么样?

awk -v replace="new value" 'm && /^[^:]+:/ { m=0 }
/^#foo:/ { m=1 }
m { sub(/^#/, ""); s(/<[^<>]*>/, replace) }1' 

这遵循了我们熟悉的模式:当我们看到感兴趣的区域开始时设置状态变量m,当我们在该区域时执行替换,当我们看到新区域开始时关闭变量(推测其条件可能是什么样子)。

要改变这一点并不难,只需在区域开始后查找固定数量的行;将状态变量设置为一个数字,并每行递减。

如果这是一个Makefile,那么使用make变量会更加优雅和健壮。

ifdef ENABLE
foo:
bar=$(barvalue)
endif

(或者仅仅是ifdef barvalue!)

相关内容

  • 没有找到相关文章

最新更新