通过sed或awk在线偏移的两个模式之间进行替换

时间:2017-09-27 18:07:15

标签: bash awk sed

我有一个大文件,内容由标题分隔。

我如何通过sed或awk将文本替换为特定标题之后的行与文件中特定字符串(不包括)之前的行之间的文本?

示例:我想在header1之后的行与string_near_end_of_file之前的行(不包括在内)之间替换EXAMPLE中的文字...

...

header1
#######
content1

header2
#######
content2

...

string_near_end_of_file

...

预期结果:

...

header1
#######
EXAMPLE

string_near_end_of_file

...

我知道sed '/pattern1/,/.. pattern2/c\substition_string'文件会在substition_stringpattern1之间替换pattern2,并且sed -n '/pattern/{n;p}' file会在pattern匹配后打印该行,但我和#39;我现在不确定这些是为了达到我既定的目标。

非常感谢任何帮助!

3 个答案:

答案 0 :(得分:2)

您可以使用此awk命令:

awk '/string_near_end_of_file/{p=0} !p; $1=="header1"{p=1; print "######\nEXAMPLE\n"}' file

<强>输出:

...

header1
######
EXAMPLE

string_near_end_of_file

...

答案 1 :(得分:1)

GNU sed:

sed -e '/header1/,/string_near/{/header1/{n;s/$/\nEXAMPLE\n/;n};/string_near/!d}' file

在范围内:

  • /header1/{n; - 跳过header1行
    • s/$/\nEXAMPLE\n/; - 用\nEXAMPLE\n
    • 替换###行尾
    • n}单独留下###和EXAMPLE行
  • /string_near/!d; - 删除除string_near
  • 以外的其他行

sed很糟糕,要求重复块内的/ START /,/ END /模式。您有时可以使用//表示最后一个正则表达式,但任何嵌套的正则表达式都限制它在/ START /,/ END /范围中的使用。

请注意,某些sed实现在关闭花括号之前需要使用分号。

另请注意,我使用行尾s/$/\nEXAMPLE\n/的替换,因为在命令行内联更容易,然后使用sed的c a或{{1} }命令,需要命令字符串中的换行符。

答案 2 :(得分:0)

awk 解决方案(假设标题行后面总是跟#######行):

awk -v repl="EXAMPLE" '!f && /header/{ f=1; n=NR; getline nl; r=$0 ORS nl }
       /string_near_end_of_file/{ f=0; print r ORS repl ORS ORS $0; next }
       f && NR>n{ next }1' file

输出:

...

header1
#######
EXAMPLE

string_near_end_of_file

...