![](/img/trans.png)
[英]Linux: How to replace all text between two lines and substitute it with the output of a variable using sed?
[英]Replace text between two lines with contents of a file stored in a variable in sed
假设我有一个名为original.txt
的文件,其中包含以下内容:
红色
蓝色
水
食物
树
灰色
白色
我还有一个名为new.txt
的文件, new.txt
包含以下内容:
绿色
黑色
黄色
紫色
现在我想编写一个脚本,用new.txt
的内容替换original.txt
blue
和gray
之间的行,所以它给了我这个结果:
红色
蓝色
绿色
黑色
黄色
紫色
灰色
白色
我为此编写了这段代码(新文件的名称并不总是相同,因此它存储在一个变量中):
newtext="new.txt"
sed -i "/blue/,/gray/{
r $newtext
d
}" original.txt
但是,在运行它时,我得到了这个废话:
red
green
black
yellow
purplegreen
black
yellow
purplegreen
black
yellow
purplegreen
black
yellow
purplegreen
black
yellow
purplewhite
我做错了什么?
这可能对你有用(GNU sed):
sed '/blue/,/gray/!b;//!d;/blue/r file2' file1
对于blue
和gray
之间的行范围,删除与该范围中的第一行或最后一行都不匹配的行,并读取要在该范围的最后一行之前插入的行。
编辑:
第一个 sed 命令/blue/,/grey/!b
匹配一系列行,即介于包含blue
的行到包含包含gray
的行之间的行。 !b
部分意味着如果这些行不在该范围内,则脱离 sed 命令,即不对这些行进行任何进一步的 sed 处理,只是正常打印。
下面的 sed 命令只会影响blue
和gray
范围内的那些行。
第二个命令//!d
表示:删除那些与范围的开始/结束不匹配的行,即blue
或gray
。 //
使用上一个/.../
命令中的正则表达式。 注意删除命令会终止该行的任何进一步 sed 处理。
下面的 sed 命令只会影响包含blue
或gray
。
第三个命令匹配包含blue
的行并从 file2 中读取行。
注意包含blue
和grey
的行由 sed 自然处理并在下一行被读入模式空间之前打印,不在blue
和gray
之间的行也是如此。
一个替代方案:
sed '/blue/,/gray/!b;//!d;/gray/e cat file2' file1
还有一个:
sed -ne '/blue/{p;r file2' -e ':a;n;/gray/!ba};p' file1
sed 用于 s/old/new/,仅此而已。 对于其他任何事情,您都应该使用 awk:
$ awk 'NR==FNR{new = new $0 ORS; next} /gray/{f=0} !f{print} /blue/{printf "%s",new; f=1}' new.txt original.txt
red
blue
green
black
yellow
purple
gray
white
以上将在任何 UNIX 机器上的任何 shell 中的任何 awk 中工作,并且不需要重复任何开始/结束正则表达式。 非常重要的是,它也可以简单地建立在你现在或将来做任何你想做的事情上! 例如,能够将开始和结束的正则表达式指定为参数:
$ awk -v beg='blue' -v end='gray' 'NR==FNR{new = new $0 ORS; next} $0~end{f=0} !f{print} $0~beg{printf "%s",new; f=1}' new.txt original.txt
广告然后你可以改变它们:
$ awk -v beg='water' -v end='tree' 'NR==FNR{new = new $0 ORS; next} $0~end{f=0} !f{print} $0~beg{printf "%s",new; f=1}' new.txt original.txt
red
blue
water
green
black
yellow
purple
tree
gray
white
您可能想做的任何事情只是使用相同结构的简单重新排列,例如不打印开始行:
$ awk -v beg='blue' -v end='gray' 'NR==FNR{new = new $0 ORS; next} $0~end{f=0} $0~beg{printf "%s",new; f=1} !f{print}' new.txt original.txt
red
green
black
yellow
purple
gray
white
和类似的调整不打印结束行或不打印两者或做任何其他事情....
我看到你要求 sed 帮助,但 ex 以更直接的方式处理这个用例。 这可能对您有用(在 shell 脚本中):
ex original.txt << EOF_EX
/blue/+1,/gray/-1 d
r new.txt
w edited.txt
q!
EOF_EX
上面打开 original.txt 进行编辑,删除从前蓝色到后灰色的行范围,读取文件 new.txt,并写出文件edited.txt。
结果:
$ cat edited.txt
red
blue
gray
green
black
yellow
purple
white
或者,您可以将“wedited.txt”替换为“wq”,它会将更改保存在 original.txt 文件中。
另外,请注意范围中的 +1 和 -1 语法,这非常方便。 例如,如果您还想删除范围边界模式“蓝色”和“灰色”,您可以删除 +1 和 -1,这意味着删除范围,包括范围边界模式。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.