如何调试jq向我投掷的stdin错误?

时间:2017-12-12 02:13:25

标签: debugging runtime-error jq

给出以下虚拟数据

[{
  "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"

问题:如何使用抛出的错误提供的信息并准确检查导致错误的对象?我想纠正任何格式错误,但数据集是如此之大,以至于我无法逐字向下滚动。

任何想法都会让我高兴,谢谢!

1 个答案:

答案 0 :(得分:3)

  1. 不是使用cat(效率低下并隐藏jq中的文件名),而是以文件名作为参数调用jq。

  2. 当我对您的过滤器和示例数据执行此操作时,收到错误消息:

    jq:error(在fulldata.json:31):无法使用字符串“submitter”索引数组

  3. 这里“31”是行号,对应于文件的末尾,即数组的结尾。所以错误信息是:“你正在尝试将索引操作(。[”submitter“])应用于数组。数组只能用整数索引,所以发生了什么?你的查询适用于对象,而不是数组。

    1. 因此,一个简单的解决方法是将您的查询包装在map()的调用中。这会取得成功。

    2. 另一种调试方法是使用debug。您可以根据需要在查询中撒出尽可能多的debug个。例如,您可以从:

      开始

      选择(debug | .submitter.user_fields.region ==“China”)

    3. 假设现在数组中存在一个虚假对象:

      {“submitter”:0}

    4. 运行我们的地图(选择(...))程序,我们得到:

      jq: error (at fulldata.json:35): Cannot index number with string "user_fields"
      

      这是您收到的错误消息,它指向发生错误的行。

      1. 如果您只想跳过异常记录,请考虑使用jq(仅限)postfix ?运算符,例如

        地图(选择(.submitter?.user_fields?.region?==“China”))

      2. 如果您想要有问题对象所在的数组中的索引, 然后考虑首先添加一个索引,可以这样做:

        foreach。[] as $ obj(-1;。+ 1; [。,$ obj])

      3. 这将数组转换为形式为[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实际上提供了大量的调试支持,包括debugtry ... catch ...error(...),如前所述;这些和其他一些好东西(例如input_line_number)记录在reference manual