问题源于jq
可能令人惊讶的默认行为:
keys
枚举按字母顺序排序的键。
.[]
根据键的输入顺序枚举值[1]
换句话说:如果您在一次传递keys
中提取对象的键,然后在另一次传递.[]
中提取其值,则相应的输出元素可能不匹配。
jq
v1.5引入了该keys_unsorted/0
功能,可以实现简单的解决方案:
# Sample input with unordered keys.
# Sorting the values results in the same order as sorting the keys,
# so the output order of values below implies the key enumeration order that was applied.
json='{ "c":3, "a":1, "b":2 }'
按输入顺序打印键,使用keys_unsorted/0
:
$ echo "$json" | jq -r 'keys_unsorted[]'
c
a
b
按输入顺序打印值,这[]
总是:
$ echo "$json" | jq -r '.[]'
3
1
2
警告:直到v1.3版本,使用.[]
导致没有保证的枚举顺序(使用了底层哈希表的键排序,这是一个实现细节);如果您仍然必须使用 v1.3,您可以使用to_entries
如下所示的方法。
[v1.3+] to_entries/0
,如user2259432 的有用答案中所使用的,还按输入顺序枚举属性:
# Extract keys
$ echo "$json" | jq -r 'to_entries | map(.key)[]'
c
a
b
# Extract values
$ echo "$json" | jq -r 'to_entries | map(.value)[]'
3
1
2
警告:在 v1.5 之前,以按键to_entries/0
排序的顺序输出键值对。
但是,由于to_entries/0
可用于枚举键和值,因此即使在 v1.5 之前的版本中,它仍然是在并行键/值提取中生成稳定枚举顺序的可行解决方案。
[v1.3+]相比之下,如果您想按键排序的顺序进行枚举:
按字母顺序打印键,使用keys/0
:
$ echo "$json" | jq -r 'keys[]'
a
b
c
按字母顺序键打印值:
$ echo "$json" | jq -r 'keys[] as $k | .[$k]'
1
2
3
一个警告重新-S
/--sort-keys
:
此选项仅适用于整个对象,输出:
$ echo "$json" | jq -Sc '.'
{"a":1,"b":2,"c":3} # Sorted by key
当您使用运算符或函数访问对象的内部时,它不适用:
$ echo "$json" | jq -S '.[]' # !! -S doesn't apply, because [] always uses input order
3
1
2
[1] 在 v1.5 之前,不保证特定的顺序,但是会导致同样的问题。