给出以下虚拟数据
[{
"submitter": {
"user_fields": {
"region": "Colombia"
}
}
}, {
"submitter": {
"user_fields": {
"region": "China"
}
}
}, {
"submitter": {
"user_fields": {
"region": "China"
}
}
}, {
"submitter": {
"user_fields": {
"region": "Mexico"
}
}
}, {
"submitter": {
"user_fields": {
"region": "Canada"
}
}
}]
包含在
中fulldata.json
我正在尝试使用
过滤对象"region": "China"
然后我希望所有满足过滤器的对象填充新文件
chinadata.json
现在这就是我所做的:
cat fulldata.json | jq 'select(.submitter.user_fields.region == "China")' > chinadata.json
实际上是一个新的
chinadata.json
已在流程中创建,它包含(似乎)所有正确的信息。
但问题是,在上一个命令运行时,我有一堆行抛出了这种错误:
jq: error (at <stdin>:45380): Cannot index number with string "user_fields"
问题:如何使用抛出的错误提供的信息并准确检查导致错误的对象?我想纠正任何格式错误,但数据集是如此之大,以至于我无法逐字向下滚动。
任何想法都会让我高兴,谢谢!
答案 0 :(得分:3)
不是使用cat
(效率低下并隐藏jq中的文件名),而是以文件名作为参数调用jq。
当我对您的过滤器和示例数据执行此操作时,收到错误消息:
jq:error(在fulldata.json:31):无法使用字符串“submitter”索引数组
这里“31”是行号,对应于文件的末尾,即数组的结尾。所以错误信息是:“你正在尝试将索引操作(。[”submitter“])应用于数组。数组只能用整数索引,所以发生了什么?你的查询适用于对象,而不是数组。
因此,一个简单的解决方法是将您的查询包装在map()
的调用中。这会取得成功。
另一种调试方法是使用debug
。您可以根据需要在查询中撒出尽可能多的debug
个。例如,您可以从:
选择(debug | .submitter.user_fields.region ==“China”)
假设现在数组中存在一个虚假对象:
{“submitter”:0}
运行我们的地图(选择(...))程序,我们得到:
jq: error (at fulldata.json:35): Cannot index number with string "user_fields"
这是您收到的错误消息,它指向发生错误的行。
如果您只想跳过异常记录,请考虑使用jq(仅限)postfix ?
运算符,例如
地图(选择(.submitter?.user_fields?.region?==“China”))
如果您想要有问题对象所在的数组中的索引, 然后考虑首先添加一个索引,可以这样做:
foreach。[] as $ obj(-1;。+ 1; [。,$ obj])
这将数组转换为形式为[i,object]的对的流,其中i是索引(从0开始)。然后,您可以轻松修改查询,以便在出现错误时,可以打印i的相应值。例如:
foreach .[] as $obj ( -1; .+1; [., $obj] )
| . as $pair
| try (.[1] | select(.submitter.user_fields.region == "China"))
catch ($pair[0] | error(tostring))
jq实际上提供了大量的调试支持,包括debug
,try ... catch ...
和error(...)
,如前所述;这些和其他一些好东西(例如input_line_number
)记录在reference manual。