首页 > 解决方案 > 使用生成的字符串作为命令的 sed

问题描述

我有一个 xml,其中包含 3 个其他 xml 文件的路径。我们将文件称为 main、cfg、config 和 engine。来自 main.xml 的相关摘录:

<cfgfile>path/to/cfg/cfg.xml</cfgfile>
<enginefile>path/to/engine/engine.xml</enginefile>
<configfile>path/to/config/config.xml</configfile>

我想用 pwd 替换“path/to/x”(并将 main、cfg、config 和 engine 复制到 pwd)。对于cfg,我可以这样做:

sed 's%path/to/cfg/cfg.xml%"$(pwd)"/cfg.xml' source_path/main.xml > ./main.xml

为了让它“更简单”,我试图通过一个循环来做到这一点:

S="";
for ele in "cfg" "engine" "config"; do
S=$S's%<'"$ele"'>.*</'"$ele"'>%<'"$ele"'>'"$(pwd)"'</'"$ele"'>;';
done;
echo $S

我在其他 3 个文件中有类似的更改。因此,与其键入所有命令,不如使用循环。我知道我可以更轻松地使用 awk 或 python,但只需使用 sed 尝试一下。所以问题是我可以使用生成的变量 S 作为 sed oneliner 中的命令(而不将其重定向到文件),例如: sed 'use $S' source_path/a.xml

标签: bashsed

解决方案


@Cyrus 评论绝对正确。XML 比您想象的要多。

如果您了解 XPath,您可以轻松地xmlstarletsed.

for a in cfgfile enginefile configfile
do
    temppath="$( xmlstarlet sel -t -m "//${a}" -v "normalize-space(node())"  main.xml | sed -e "s#path/to/[^\/]\+#$( pwd )#g" )"
    tempxml="$( xmlstarlet ed -u "//${a}" -v "${temppath}" main.xml )" && echo "${tempxml}" > main.xml
done

这确保您不会破坏 XML 结构。不幸的是,XPath 中没有 regex-match-replace 函数(据我所知)。


推荐阅读