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


9

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

如何使用sed替换多行字符串给我留下了深刻的印象antak回答 ,多行替换Bruce Ediger回答

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

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

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

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

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

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

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


我发现您对“视觉障碍”一词的使用异常且令人困惑。您是指一组连续的完整行吗?
斯科特,

是的,我正在编辑问题以避免混淆。
gibies '16

替换文字的来源是什么?是在文件中还是“仅在程序员心中”?
don_crissti

这是用于外壳程序脚本的情境修补。因此,替换文本的来源是程序员的思想(sed或运行ex命令的主脚本)。
gibies

Don Crisstir如果替换文本的源位于文件中,我将使用read file命令从另一个文件复制文本。
gibies

Answers:


10

我建议使用Ç焊割命令(这基本上是一个d elete再加上一个 PPEND,虽然追加仅适用于这正是你想要的这里的范围内的最后一行):

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

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

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

作为非标准扩展名。

换行符和反斜杠字符必须在替换文本中转义(带有反斜杠)。


变化命令工作正常,都sedex一致好评。非常感谢你。
gibies

有没有什么办法可以避免使用“ \”,并在此文档中使用布鲁斯·埃迪格Bruce Ediger)在“ 多行替换”中建议sedex语法。
gibies '16

如果使用该r问题的其他答案中讨论的命令,则不需要反斜杠。我不确定您将如何在此处使用here文档sed
G-Man说'恢复莫妮卡'

8

使用GNU sed

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

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

对于范围内的行/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为true),如果是,则打印New Code并设置f为1,然后跳过其余命令并跳至该next行。

对于超出范围的行/3/,/5/,不会进行跳转,并且1会导致打印该行。更详细地说,1是一个条件。由于1不为零,因此条件评估为true。由于没有与该条件相关联的操作,因此将执行默认操作以打印行。因此,这1是在线印刷的简称。

要在适当位置更改文件,-i inplace可以将该选项与GNU awk4.1或更高版本一起使用:

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

凉。我不擅长awk,请您解释一下您的awk表情
Rahul

1
@Rahul当然。我添加了对awk代码的解释。
John1024 '16

1
谢谢约翰这正是我想要的。
gibies

删除块非常简单,然后在最后一行添加新的块:sed '/3/,/4/d;/5/cNew Code' awk '/5/{print "New Code"}/3/,/5/{next}1'
Costas

1

基于以上讨论,我提出了一个解决方案,使用 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-man使我知道change命令,并给出有关点的说明。无论sedex份额几乎相同的语法变更指令(也可用于删除命令,附加命令等)。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.