sed - 替换变量替换的两个模式匹配之间的多行
问题描述
我正在尝试替换跨越多行的文件中的一些文本。有一个开始模式和一个结束模式要匹配。
<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,}
似乎没有任何效果。我试过双引号,改变分隔符我只是在这里没有任何运气。我在这里查看了许多示例,但似乎没有一个示例同时解决变量替换问题。
解决方案
这可能对您有用(GNU sed):
sed -i'.bak' -ne '\#'"$BEGIN"'#{p;:a;n;\#'"$END"'#!ba;i\'"$REPLACE" -e '};p' file
使用该-i
选项备份原始文件。使用该-n
选项禁止自动打印图案空间。使用-e
选项允许 sed 命令占用一行。
regexp 的常规分隔符是/
字符,但是 bash 变量可能包含它,因此请使用替代项(在这种情况下#
已选择)。
如果当前行包含 in 的字符串$BEGIN
,则打印它,并循环直到 in 的字符串$END
是当前行。将字符串插入$REPLACE
并打印所有其他行(包括包含 的行$END
)。
如果$REPLACE
包含多行,除最后一行之外的每一行都需要以 结尾\
,另一种方法是将替换的内容放在一个文件中并使用以下解决方案。
sed -i'.bak' -ne '\#'"$BEGIN"'#{p;:a;n;\#'"$END"'#!ba;e cat '"$FILE"' -e '};p' file
where $FILE
now 包含替换,但是由于它使用e
命令(调用cat
命令),$FILE
因此需要首先导出变量,例如
cat <<\!>replacementFile.txt
foo
bar
baz
!
export FILE="replacementFile.txt"
推荐阅读
- python - PyTorch 前向传播在相同样本上返回不同的 logits
- c# - C# 程序在朋友的 PC 上立即关闭
- c# - 如何检查节点的存在和具有特定属性的节点是否存在?
- activemq-artemis - 在 docker 上集群 Artemis 的问题
- ios - 本地主机上的开发 node.js 服务器在 swiftUI 应用程序中返回 nil,但在浏览器中不返回
- python - 如何将具有不同数字的小时/分钟列转换为 python/pandas 中的日期时间对象?
- vim - 是否可以在 vim 缩写 id 中包含回车?
- r - 如何为对数正态分布列绑定蒙特卡罗模拟结果?
- sql - 使用 SQL 请求复制行和编辑值,但需要改进一下
- php - 在前端监控 PHP 执行的正确方法是什么?