我正在尝试替换跨多行的文件中的某些文本。有一个开始模式和一个结束模式要匹配。
<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,}
似乎没有任何效果。我试过双引号,更改了定界符,但我在这里没有任何运气。我在这里查看了许多示例,但是似乎没有一个示例可以同时解决变量替换问题。
答案 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"