在 shell 脚本中使用 xmlstarlet 读取脚本变量值,如果该字符串不存在,则插入到特定部分下的输出 xml 文件中

问题描述 投票:0回答:1

我在 shell 脚本中使用的 parse yaml 实用程序通过 eval 命令生成如下变量

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 在我的 outputpolicy.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

但我正在寻找的是在我的脚本中使用 xmlstarlet 来读取上述脚本变量“$(eval echo $${f}inboundsession) 的输出,并在下面的policy.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>
xml shell xslt xml-parsing xmlstarlet
1个回答
0
投票

以下是如何添加

rate-limit-by-key
节点,如果存在则不添加。 要使用 shell 变量作为输入值,请参阅下面的第三个要点。

# shellcheck shell=sh disable=SC2016

xmlstarlet edit -O \
  -a '/policies/inbound/base[not(following-sibling::rate-limit-by-key)]' \
    -t elem -n 'rate-limit-by-key' \
  --var lim '$prev' \
  -s '$lim' -t attr -n 'calls' -v 'xx' \
  -s '$lim' -t attr -n 'renewal-period' -v 'yy' \
  -s '$lim' -t attr -n 'counter-key' \
    -v '@(Regex.Match(context.x.y.GetValueOrDefault("xxxxxxx",""), @"^[.x-y]*")?.Value)' \
"${infile:-file.xml}"

地点:

  • -a …
    (又名
    --append
    )添加一个跟随兄弟节点,它执行 仅当其参数与现有节点匹配时,XPath 谓词 (
    not(following-sibling::rate-limit-by-key)
    ) 指定一个 add-if-not-exists 条件
  • 如果
    -a …
    不匹配任何内容,则
    $prev
    [📌] 将匹配 什么都没有,这将使以下依赖于
    $prev
    -s …
    无效 (又名
    --subnode
    )选项
  • 此处的
    -v
    (又名
    --value
    )选项使用字符串文字,但它们 可以更改为拉入 shell 变量 (
    -v "${somevar}"
    ) 或命令替换的结果 (
    -v "$(somecmd)"
    )

[📌] 在

xmlstarlet edit
命令中
--var
定义了一个命名变量,以及反向引用
$prev
变量(又名
$xstar:prev
)指的是由最多创建的节点 最近的
-s
-i
-a
选项都定义或重新定义它 (见
xmlstarlet.txt
有关
--var
$prev
的一些示例)。


请注意,您发布的预期输出不是 XML,因为它包含 XML 序列化程序将在属性值中引用字符 可能的输出为

&quot;

给定这个输入文件,

<policies>
  <inbound>
    <base/>
  </inbound>
</policies>

上面的命令产生,

<policies>
  <inbound>
    <base/>
    <rate-limit-by-key calls="xx" renewal-period="yy" counter-key="@(Regex.Match(context.x.y.GetValueOrDefault(&quot;xxxxxxx&quot;,&quot;&quot;), @&quot;^[.x-y]*&quot;)?.Value)"/>
  </inbound>
</policies>
© www.soinside.com 2019 - 2024. All rights reserved.