json 如何在jq中按IP地址排序?

ikfrs5lh  于 2023-05-30  发布在  其他
关注(0)|答案(2)|浏览(172)

如何使用jq按IPv4地址值(32位整数,而不是字母数字)对对象数组进行排序?
为了视觉清晰,我用一些额外的格式来说明我的意思:

$ echo '
    {"name": "dns", "ip": "4.4.4.4"}
    {"name": "host1", "ip": "10.9.9.9"}
    {"name": "host2", "ip": "10.10.10.10"}
' |jq -sr '.|=sort_by(.ip) |.[] |[.name, .ip] |@tsv'

host2   10.10.10.10
host1   10.9.9.9
dns 4.4.4.4

这个|=sort_by(.ip)按字母数字顺序排序,但我希望数组按“IPnumerically”排序。如果我有这样的TSV格式,我可以使用外部工具(例如sort的非POSIX -V扩展)在外部完成这一工作,但是有没有办法在jq中完成这一工作?

$ echo '
    {"name": "dns", "ip": "4.4.4.4"}
    {"name": "host1", "ip": "10.9.9.9"}
    {"name": "host2", "ip": "10.10.10.10"}
    ' |jq -sr '.|=sort_by(.ip) |.[] |[.name, .ip] |@tsv' |sort -t$'\t' -Vk2
dns 4.4.4.4
host1   10.9.9.9
host2   10.10.10.10
eqzww0vc

eqzww0vc1#

你可以简单地分割ip并将其转换为一个数字数组:

sort_by(.ip | split(".")[] | tonumber)

Full命令(注意,不需要在开始时重新分配(.|=)):

$ echo '
    {"name": "dns", "ip": "4.4.4.4"}
    {"name": "host1", "ip": "10.9.9.9"}
    {"name": "host2", "ip": "10.10.10.10"}
' | jq -sr 'sort_by(.ip | split(".")[] | tonumber) | .[] | [.name, .ip] | @tsv'

dns 4.4.4.4
host1   10.9.9.9
host2   10.10.10.10
bqjvbblv

bqjvbblv2#

要使用jq按IPv4地址值作为32位整数对对象数组进行排序,可以在排序之前将IP地址转换为整数。下面是一个如何实现此目标的示例:

echo '
    {"name": "dns", "ip": "4.4.4.4"}
    {"name": "host1", "ip": "10.9.9.9"}
    {"name": "host2", "ip": "10.10.10.10"}
' | jq -sr '
  .[]
  | .ip |= split(".") | map(tonumber)
  | .|=sort_by(.ip[0] * 256 * 256 * 256 + .ip[1] * 256 * 256 + .ip[2] * 256 + .ip[3])
  | [.name, .ip | join(".")]
  | @tsv
'

这将把每个IP地址转换成一个整数数组,表示四个八位字节。然后,它通过将相应的八位字节乘以其相应的权重并将它们相加来计算32位整数值。最后,根据计算出的整数值对数组进行排序。
输出将是:

dns     4.4.4.4
host1   10.9.9.9
host2   10.10.10.10

现在,数组基于IP地址的整数表示进行“IP数字”排序。
更新基于一个好的评论:下面是jq命令的更新版本,它按IPv4地址值对对象数组进行排序,而不将它们转换为单个数字:

echo '
    {"name": "dns", "ip": "4.4.4.4"}
    {"name": "host1", "ip": "10.9.9.9"}
    {"name": "host2", "ip": "10.10.10.10"}
' | jq -s 'sort_by(.ip | split(".") | map(tonumber)) | .[] | [.name, .ip] | @tsv'

相关问题