繁体   English   中英

用存储在 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 bluegray之间的行,所以它给了我这个结果:

红色
蓝色
绿色
黑色
黄色
紫色
灰色
白色

我为此编写了这段代码(新文件的名称并不总是相同,因此它存储在一个变量中):

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

对于bluegray之间的行范围,删除与该范围中的第一行或最后一行都不匹配的行,并读取要在该范围的最后一行之前插入的行。

编辑:

第一个 sed 命令/blue/,/grey/!b匹配一系列行,即介于包含blue的行到包含包含gray的行之间的行。 !b部分意味着如果这些行不在该范围内,则脱离 sed 命令,即不对这些行进行任何进一步的 sed 处理,只是正常打印。

下面的 sed 命令只会影响bluegray范围内的那些行。

第二个命令//!d表示:删除那些与范围的开始/结束不匹配的行,即bluegray //使用上一个/.../命令中的正则表达式。 注意删除命令会终止该行的任何进一步 sed 处理。

下面的 sed 命令只会影响包含bluegray

第三个命令匹配包含blue的行并从 file2 中读取行。

注意包含bluegrey的行由 sed 自然处理并在下一行被读入模式空间之前打印,不在bluegray之间的行也是如此。

一个替代方案:

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM