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

问题描述 投票:0回答:1

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

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

开始图案

<User darthvader>

结束图案

</User>

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

我需要使用变量并且这些变量需要扩展。我认为这就是它开始对我不起作用的地方。我认为

<User
darthvader
之间的空格也可能存在问题。

以下面的例子为例;

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,}

似乎没有什么效果。我尝试过双引号,更改分隔符,但我在这里运气不佳。我在这里查看了许多示例,但似乎没有一个示例能够同时解决变量替换问题。

sed
1个回答
1
投票

这可能对你有用(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
包含多行,除了最后一行之外的每一行都需要以
\
结尾,另一种方法是将替换的内容放在文件中并使用以下解决方案。

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"
© www.soinside.com 2019 - 2024. All rights reserved.