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

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

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

我印象深刻的是如何使用 sed 替换多行字符串?回答者 安塔克多行替换回答者布鲁斯·艾迪格

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

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

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

    sed -i '/marker1/,/marker2/s/.*/new text (code)/' filename
    

它将为每个流重复插入新文本(代码)。因此,我必须使用类似于建议的内容将视觉块作为一个流安塔克较早,但针对的是块(不是整个文件)。

  1. 正如所提到的布鲁斯·艾迪格可以尝试以点开头ex的附加功能,但我的新文本(代码)包含以点开头的行,这可以被视为附加语法的点。在这种情况下我该如何使用它?a.

  2. exdd“行数”可能会删除多行,但是如果我在 /marker1/ 和 /marker2/ 之间有一个块,其行数不固定(变化)要替换为新文本(代码),该怎么办它 ?

答案1

我建议使用Change 命令(本质上是一个delete 加上Apend,尽管追加仅应用于范围中的最后一行,这正是您想要的):

sed -i '/marker1/,/marker2/c\
New text 1\
New text 2' filename

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

sed '/marker1/,/marker2/cNew text 1\
New text 2' filename

作为非标准扩展。

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

答案2

使用 GNU sed

要替换从匹配行开始3并继续到匹配行的5New Code

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

对于 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

使用 awk

使用 awk 执行相同操作:

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

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

对于范围之外的行/3/,/5/,不会进行跳转并1导致打印该行。更详细地说,1是一个条件。由于1不为零,因此条件计算结果为 true。由于没有与条件关联的操作,因此执行默认操作,即打印该行。这1是 print-the-line 的简写。

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

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

答案3

基于上面的讨论我想出了一个解决方案ex

seq 15 > test1.txt
ex test1.txt << EOEX
/^7/,/^9/c
abcd
123
.xyz
hfr4
.
w!
q
EOEX
cat test1.txt

上面给出

1
2
3
4
5
6
abcd
123
.xyz
hfr4
10
11
12
13
14
15

谢谢g男让我了解更改命令并对点进行澄清。sed和都ex共享几乎相似的更改命令语法(也适用于删除命令、追加命令等)。

相关内容