我在 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>
以下是如何添加
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 序列化程序将在属性值中引用字符 可能的输出为
"
。
给定这个输入文件,
<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("xxxxxxx",""), @"^[.x-y]*")?.Value)"/>
</inbound>
</policies>