如何用Bash Shell将文件中指定文本块替换为其他文件内容
问题描述
我需要将file_to_change.xml中的指定文本块替换为changes.xml的全部内容,待替换的目标块保存在aux.xml中(对应原文件里的一个<client>标签内容)。仅可使用sed、awk这类系统核心工具,不能用外部工具,且与全文件替换的方案不同,仅替换指定块。
各文件内容
file_to_change.xml
<clients> <client> <name>Bob</name> <age>18</age> </client> <client> <name>Alice</name> <age>12</age> </client> <client> <name>Carlos</name> <age>28</age> </client> </clients>
changes.xml
<client> <name>Carlita</name> <age>17</age> </client>
aux.xml(待替换的目标块)
<client> <name>Carlos</name> <age>28</age> </client>
我尝试过以下命令,但未达到预期效果:
sed -i -e '1r changes.xml' -e '1,/r aux.xml/d' file_to_change.xml
期望修改后的file_to_change.xml内容:
<clients> <client> <name>Bob</name> <age>18</age> </client> <client> <name>Alice</name> <age>12</age> </client> <client> <name>Carlita</name> <age>17</age> </client> </clients>
解决方案
方法1:使用awk实现
通过awk读取目标块和替换内容到内存,遍历原文件时匹配目标块并替换,其他内容正常输出:
awk ' BEGIN { # 读取aux.xml目标块存入target while (getline line < "aux.xml") { target = target line "\n" } # 读取changes.xml替换内容存入replace while (getline line < "changes.xml") { replace = replace line "\n" } close("aux.xml") close("changes.xml") current = "" } { current = current $0 "\n" # 匹配到目标块则输出替换内容,清空累积 if (current == target) { print replace current = "" } else if (length(current) > length(target)) { # 累积内容过长未匹配,逐行输出前面的内容 while (length(current) > length(target)) { n = index(current, "\n") print substr(current, 1, n-1) current = substr(current, n+1) } } } END { # 输出剩余内容 printf "%s", current } ' file_to_change.xml > temp.xml && mv temp.xml file_to_change.xml
方法2:使用sed实现(针对固定目标块)
直接针对目标块的多行内容进行匹配和替换,适合目标块固定的场景:
sed -i ' /<client>/{ N N N N # 匹配目标块的5行内容 / <client>\n <name>Carlos<\/name>\n <age>28<\/age>\n <\/client>/{ # 替换为changes.xml的内容 c\ <client>\n <name>Carlita<\/name>\n <age>17<\/age>\n <\/client> } } ' file_to_change.xml
内容的提问来源于stack exchange,提问作者culpinha
相关产品推荐
相关产品推荐

