替换变量替换的两个模式匹配之间的多行

时间:2019-07-19 03:22:08

标签: sed

我正在尝试替换跨多行的文件中的某些文本。有一个开始模式和一个结束模式要匹配。

<User darthvader>
    home    /deathstar/
    lightsaber    red
</User>

开始模式

<User darthvader>

结束模式

</User>

替换之间的所有内容。此文件中将有多个使用相同格式的不同用户。

我需要使用变量,并且需要扩展这些变量。我认为这是开始对我不起作用的地方。我认为<Userdarthvader之间的空格也可能有问题。

采用以下示例;

BEGIN
    home    /deathstar/
    lightsaber    red
END

如果我使用此sed命令

#!/bin/bash
FILE_TO_EDIT="/file.txt"

sed -e '/BEGIN/{ N; s/BEGIN.*END/MAY THE FORCE BE WITH YOU/ }' ${FILE_TO_EDIT} >${FILE_TO_EDIT}.tmp && mv ${FILE_TO_EDIT}{.tmp,}

这给了我

BEGIN
MAY THE FORCE BE WITH YOU
END

所以我知道我走对了。但是一旦我尝试做类似的事情

#!/bin/bash
FILE_TO_EDIT="/file.txt"
USER="darthvader"
BEGIN="<User ${USER}>"
END="</User>"
REPLACE="Booyah!"

sed -e "/${BEGIN}/{ N; s/${BEGIN}.*${END}/${REPLACE}/ }" ${FILE_TO_EDIT} >${FILE_TO_EDIT}.tmp && mv ${FILE_TO_EDIT}{.tmp,}

似乎没有任何效果。我试过双引号,更改了定界符,但我在这里没有任何运气。我在这里查看了许多示例,但是似乎没有一个示例可以同时解决变量替换问题。

1 个答案:

答案 0 :(得分:0)

这可能对您有用(GNU sed):

sed -i'.bak' -ne '\#'"$BEGIN"'#{p;:a;n;\#'"$END"'#!ba;i\'"$REPLACE" -e '};p' file

使用-i选项备份原始文件。使用-n选项可禁止自动打印图案空间。使用-e选项允许sed命令占用一行。

正则表达式的常规定界符是/字符,但是bash变量可能包含它,因此请使用替代字符(在这种情况下,已选择#)。

如果当前行包含$BEGIN中的字符串,请打印并循环播放,直到$END中的字符串为当前行。将字符串插入$REPLACE并打印所有其他行(包括包含$END的行)。

如果$REPLACE包含多行,但每行但最后一行需要以\结尾,另一种方法是将replace的内容放置在文件中,并使用以下解决方案。

sed -i'.bak' -ne '\#'"$BEGIN"'#{p;:a;n;\#'"$END"'#!ba;e cat '"$FILE"' -e '};p' file

$FILE现在包含替换项,但是由于它使用e命令(称为cat命令),因此$FILE变量需要首先导出,例如

cat <<\!>replacementFile.txt
foo
bar
baz
!

export FILE="replacementFile.txt"
相关问题