如何使用 sed 或 ex 用新的文本块(代码)替换块(多行代码)?

gib*_*ies 12 sed ex

我必须用另一个文本块替换文件中的一大块文本(shell 脚本代码)。

我对如何使用 sed 替换多行字符串印象深刻antak回答 ,多线替换Bruce Ediger回答

但是我在使用它们时遇到了一些麻烦。

  1. antak在他的回答中已经提到,1h;2,$H;$!d;g;对于大文件,不建议将整个文件 ( )流式传输到缓冲区,因为它会导致内存过载。

  2. 我知道sed可以与块功能一起使用以保持块外的文本不变。我想使用这个功能。但如果我使用,

    sed -i '/marker1/,/marker2/s/.*/new text (code)/' filename
    
    Run Code Online (Sandbox Code Playgroud)

它将为每个流重复插入新文本(代码)。因此,我必须将可视块作为一个流,使用类似于antak之前建议的内容,但用于块(不是用于整个文件)。

  1. 正如Bruce Ediger提到的,可以尝试以(点)ex开头的附加功能,但我的新文本(代码)包含以点开头的行,这可能被认为是附加语法的点。在这种情况下我该如何使用它?a.

  2. ex's dd'number of lines' 可能会删除多行,但是如果我在 /marker1/ 和 /marker2/ 之间有一个块,其中的行数不固定(变化)将被替换为新文本(代码),该怎么办它 ?

G-M*_*ca' 14

我建议使用c hange 命令(它本质上是一个d elete 加上一个ppend,尽管 append 仅应用于范围中的最后一行,这正是您在这里想要的):

sed -i '/marker1/,/marker2/c\
New text 1\
New text 2' filename
Run Code Online (Sandbox Code Playgroud)

这里使用 GNUsed的语法进行就地编辑 ( -i)。该c命令在其他方面是标准且可移植的。GNUsed支持:

sed '/marker1/,/marker2/cNew text 1\
New text 2' filename
Run Code Online (Sandbox Code Playgroud)

作为非标准扩展。

必须在替换文本中对换行符和反斜杠字符进行转义(使用反斜杠)。


Joh*_*024 9

使用 GNU sed

要更换启动线匹配的行3,并继续到线匹配5具有New Code

$ seq 8 | sed '/3/,/5/{/5/ s/.*/New Code/; t; d}'
1
2
New Code
6
7
8
Run Code Online (Sandbox Code Playgroud)

对于 range 中的行/3/,/5/,我们测试该行是否匹配5(意味着这是组中的最后一行),如果匹配,我们将替换为 insert New Code。如果进行了替换,则t命令告诉 sed 跳转到命令的末尾(在这种情况下New Code会打印)。如果没有,该d命令会告诉 sed 删除该行。

所有其他行都正常打印。

要就地更改文件,-i可以使用该选项:

sed -i.bak '/3/,/5/{/5/ s/.*/New Code/; t; d}' file
Run Code Online (Sandbox Code Playgroud)

使用 awk

使用 awk 做同样的事情:

$ seq 8 | awk '/3/,/5/{if (!f)print "New Code"; f=1; next}; 1'
1
2
New Code
6
7
8
Run Code Online (Sandbox Code Playgroud)

awk 命令/3/,/5/专门处理范围内的行。对于该范围内的行,我们测试是否f为零(即,如果!f为真),如果是,则打印New Code并设置f为 1,然后跳过其余命令并跳转到该next行。

对于 range 之外的行/3/,/5/,不进行跳转并1导致打印该行。更详细地说,1是一个条件。因为1不为零,条件评估为真。因为没有与条件相关联的操作,所以执行默认操作,即打印该行。因此1是print-the-line的简写。

要就地更改文件,该-i inplace选项可用于 GNU awk4.1 或更高版本:

awk -i inplace '/3/,/5/{if (!f)print "New Code"; f=1; next} 1' file
Run Code Online (Sandbox Code Playgroud)