You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Shell脚本中用xmlstarlet读取变量并插入XML指定节点

问题解决:基于Shell变量与xmlstarlet实现XML节点的条件插入

现有环境与生成的变量

解析YAML后通过eval生成的policy相关变量如下:

policy1_name='ipfilter'
policy1_scope='api'
policy1_apiname='apiname'
policy1_inboundsession='rate-limit-by-key calls="25" renewal-period="60"
counter-key="@\(Regex.Match\(context.xxx.xxxx.GetValueOrDefault\("X-xxxxxxx-For",""\), @"^[.0-9]*"\)?.Value\)'
policy1_outboundsession_ipAddressesFrom='1xxxxxxxx'
policy1_outboundsession_ipAddressesTo='1yyyyyyy'
policy1_=' policy1_name policy1_scope policy1_apiname policy1_inboundsession policy1_outboundsession'
policy1_outboundsession_=' policy1_outboundsession_ipAddressesFrom policy1_outboundsession_ipAddressesTo'
policy_=' policy1'

现有代码片段

当前使用xmlstarlet操作XML的代码:

for g in $(eval echo \$${f}_apiname); do
     echo " this policy will be applied to apis,$(eval echo \$${f}_apiname)"
    done
      if [ -z "$(eval echo \$${f}_inboundsession_)" ]; then
        echo 'the inbound session is not present'
      else
        echo 'the inbound session is present and append the policy settings to inbound'
        xmlstarlet ed -O  -s '//inbound' -t elem -n rate-limit-by-key  -i '//inbound/rate-limit-by-key' -t attr -n calls -v xx -i '//inbound/rate-limit-by-key' -t attr -n renewal-period -v yy -i '//inbound/rate-limit-by-key' -t attr -n counter-key -v '@(Regex.Match(context.x.y.GetValueOrDefault("xxxxxxx",""), @"^[.x-y]*")?.Value)' policy.xml > io_ou_ipfilter.xml

需求目标

读取$(eval echo $${f}_inboundsession)变量的值,检查该内容对应的XML元素是否已存在于policy.xml的<inbound>节点下;若不存在则插入该元素,最终生成如下XML结构:

<policies>
    <inbound>
      <base />
      <rate-limit-by-key calls="xxx" renewal-period="xx" counter-key="@(Regex.Match(context.x.y.GetValueOrDefault("xxxxxxx",""), @"^[.x-y]*")?.Value)" />
    </inbound>
    <backend>
      <base />
    </backend>
    <outbound>
      <base />
    </outbound>
    <on-error>
      <base />
    </on-error>
</policies>

解决方案

完整修改后的脚本

for g in $(eval echo \$${f}_apiname); do
    echo "此策略将应用于API: $(eval echo \$${f}_apiname)"
done

# 读取并处理inboundsession变量,还原成合法XML片段
INBOUND_POLICY=$(eval echo \$${f}_inboundsession | sed 's/&quot;/"/g' | tr '\n' ' ')
POLICY_NAME=$(echo "$INBOUND_POLICY" | awk '{print $1}')

if [ -z "$INBOUND_POLICY" ]; then
    echo "inbound会话策略不存在"
else
    # 检查目标元素是否已存在于inbound节点
    EXISTS=$(xmlstarlet sel -t -c "//inbound/${POLICY_NAME}" policy.xml)
    if [ -z "$EXISTS" ]; then
        echo "inbound会话策略不存在,将其插入到inbound节点"
        # 插入元素:先创建临时节点,再重命名并注入属性内容
        xmlstarlet ed -O \
            -s '//inbound' -t elem -n "temp" -v "$INBOUND_POLICY" \
            -r '//inbound/temp' -v "$POLICY_NAME" \
            policy.xml > io_ou_ipfilter.xml
    else
        echo "inbound会话策略已存在,无需操作"
        cp policy.xml io_ou_ipfilter.xml
    fi
fi

关键逻辑说明

  1. 变量格式处理:
    • 用sed替换&quot;为双引号,tr消除换行符,确保XML片段格式合法。
    • 提取元素名称(如rate-limit-by-key)用于后续存在性检查。
  2. 存在性验证:
    • 通过xmlstarlet sel查询<inbound>节点下的目标元素,返回空则说明元素不存在。
  3. 条件插入:
    • 若元素不存在,先创建临时节点注入完整的策略内容,再重命名为目标元素名称,确保属性被正确解析。

内容的提问来源于stack exchange,提问作者Vowneee

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 10:27:52