我正在使用firewalld XML 文件,如下所示:
<?xml version="1.0" encoding="utf-8"?>
<zone>
<short>Public</short>
<description>For use in public areas. You do not trust the other computers on networks to not harm your computer. Only selected incoming connections are accepted.</description>
<service name="ssh"></service>
<service name="dhcpv6-client"></service>
<service name="cockpit"></service>
<service name="https"></service>
<service name="http"></service>
<port port="5000" protocol="tcp"></port>
<port port="5001" protocol="tcp"></port>
<port port="9999" protocol="tcp"></port>
<port port="9998" protocol="tcp"></port>
<rule>
<protocol value="vrrp"></protocol>
<accept></accept>
</rule>
</zone>
我想向其中添加几个新的 TCP 端口,对它们进行排序并确保它们是唯一的
kislyuk/yq 提供
xq
命令,可用于使用 jq
语法操作 XML 文件。
对于这种情况,只需将另一个对象(包装到数组中)附加到现有数组,然后对其应用
unique
(这也会对项目进行排序)。请注意,端口号作为字符串进行处理,因此为了按数字顺序对它们进行排序,请使用 tonumber
进行转换以进行比较。最后,-x
标志会将结果转换回 XML。
xq -x '.zone.port |= (
. + [{"@port": "993", "@protocol": "tcp"}]
| unique_by(."@port" | tonumber)
)' file.xml
<zone>
<short>Public</short>
<description>For use in public areas. You do not trust the other computers on networks to not harm your computer. Only selected incoming connections are accepted.</description>
<service name="ssh"></service>
<service name="dhcpv6-client"></service>
<service name="cockpit"></service>
<service name="https"></service>
<service name="http"></service>
<port port="993" protocol="tcp"></port>
<port port="5000" protocol="tcp"></port>
<port port="5001" protocol="tcp"></port>
<port port="9998" protocol="tcp"></port>
<port port="9999" protocol="tcp"></port>
<rule>
<protocol value="vrrp"></protocol>
<accept></accept>
</rule>
</zone>
如果您想一次添加多个条目,请考虑使用
--args
将它们作为命令行参数读取(自 jq 1.6 起可用):
xq -x '.zone.port |= (
. + [$ARGS.positional | _nwise(2) | {"@port": first, "@protocol": last}]
| unique_by(."@port" | tonumber)
)' file.xml --args 6543 tcp 210 udp
<zone>
<short>Public</short>
<description>For use in public areas. You do not trust the other computers on networks to not harm your computer. Only selected incoming connections are accepted.</description>
<service name="ssh"></service>
<service name="dhcpv6-client"></service>
<service name="cockpit"></service>
<service name="https"></service>
<service name="http"></service>
<port port="210" protocol="udp"></port>
<port port="5000" protocol="tcp"></port>
<port port="5001" protocol="tcp"></port>
<port port="6543" protocol="tcp"></port>
<port port="9998" protocol="tcp"></port>
<port port="9999" protocol="tcp"></port>
<rule>
<protocol value="vrrp"></protocol>
<accept></accept>
</rule>
</zone>
pmf 的答案是正确的,但是当我问我的问题时,我提到了另一个 yq 可执行文件(mikefarah/yq)。这是用 Go 编写的。 它的语法略有不同(最新版本使用 +@ 作为属性前缀,并且仍然没有“tonumber”):
yq -p xml -o xml '.zone.port |= (
. + [{"+@port":"8500","+@protocol":"tcp"}]
| sort_by(."+@port")
| unique_by(."+@port" + ."+@protocol")
)' /etc/firewalld/zones/public.xml
此语法确保端口/协议数组是唯一的且已排序(作为字符串)。