How can I use jq to sort an array of objects by an IPv4 address value as a 32-bit integer rather than alphanumerically?
An illustration of what I mean with some extra formatting for visual clarity:
$ 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
This |=sort_by(.ip)
sorts in alphanumeric order, but I'd like the array sorted "IPnumerically". If I have it in a TSV format like this, I can use external tools (such as this non-POSIX -V
extension to sort
) to do this externally afterward, but is there a way to do this within 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
You can simply split the ip and convert it to an array of numbers:
sort_by(.ip | split(".")[] | tonumber)
Full command (note that the reassigning (.|=
) at the beginning is not needed):
$ 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