简体   繁体   English

循环遍历要使用jq从JSON文件中提取的密钥列表

[英]Looping over a list of keys to extract from a JSON file with jq

I'm trying to extract a series of properties (named in an input file) in jq and getting error when I feed those from bash via a loop: 我试图在jq中提取一系列属性(在输入文件中命名),并在通过循环从bash馈入这些属性时遇到错误:

while read line; do echo $line; cat big.json | jq ".$line"; sleep 1; done < big.properties.service

cfg.keyload.service.count
jq: error: syntax error, unexpected INVALID_CHARACTER, expecting $end (Unix shell quoting issues?) at <top-level>, line 1:

When i try to do it manually it works 当我尝试手动进行操作时

$ line=cfg.keyload.service.count
$ echo $line
cfg.keyload.service.count
$ cat big.json | jq ".$line"
1

Is there any way to get it work in loop? 有什么办法可以使其循环工作?

Here is example 这是例子

cat >big.json <<EOF
{
  "cfg": {
    "keyload": {
      "backend": {
    "app": {
      "shutdown": {
        "timeout": "5s"
                  },
      "jmx": {
        "enable": true
                    }
           }
       }
     }
}
}
EOF

cat >big.properties.service <<EOF
cfg.keyload.backend.app.shutdown.timeout
cfg.keyload.backend.app.jmx.enable
cfg.keyload.backend.app.jmx.nonexistent
cfg.nonexistent
EOF

...output should be: ...输出应为:

cfg.keyload.backend.app.shutdown.timeout
"5s"
cfg.keyload.backend.app.jmx.enable
true
cfg.keyload.backend.app.jmx.nonexistent
null
cfg.nonexistent
null

Immediate Issue - Invalid Input 立即发布-无效的输入

The "invalid character" at hand here is almost certainly a carriage return. 这里的“无效字符”几乎可以肯定是回车。 Use dos2unix to convert your input file to a proper UNIX text file, and your original code will work (albeit very inefficiently, rereading your whole big.json every time it wants to extract a single property). 使用dos2unix将您的输入文件转换为正确的UNIX文本文件,您的原始代码将起作用(尽管效率很低,每次要提取单个属性时都重新big.json整个big.json )。

Performant Implementation - Loop In JQ, Not Bash 性能实现-在JQ中循环,而不是Bash

Don't use a bash loop for this at all -- it's much more efficient to have jq do the looping. 根本不要为此使用bash循环-让jq进行循环会更有效。

Note the sub("\\r$"; "") used in this code to remove trailing carriage returns so it can accept input in DOS format. 请注意此代码中使用的sub("\\r$"; "")来删除尾随的回车符,以便它可以接受DOS格式的输入。

jq -rR --argfile infile big.json '
sub("\r$"; "") as $keyname
| ($keyname | split(".")) as $pieces
| (reduce $pieces[] as $piece ($infile; .[$piece]?)) as $value
| ($keyname, ($value | tojson))
' <big.properties.service

properly emits as output, when given the inputs in the question: 当给出问题的输入时,正确地发出作为输出:

cfg.keyload.backend.app.shutdown.timeout
"5s"
cfg.keyload.backend.app.jmx.enable
true
cfg.keyload.backend.app.jmx.nonexistent
null
cfg.nonexistent
null

Your properties file is effectively paths in the json that you want to retrieve values from. 您的属性文件实际上是您要从中检索值的json中的路径。 Convert them to paths that jq recognizes so you can get those values. 将它们转换为jq识别的路径,以便获得这些值。 Just make an array of keys that would need to be traversed. 只需排列一系列需要遍历的键即可。 Be sure to read your properties file as raw input ( -R ) since it's not json, and use raw output ( -r ) to be able to output the paths as you want. 由于它不是json,因此请确保将属性文件读取为原始输入( -R ),并使用原始输出( -r )来输出所需的路径。

$ jq --argfile big big.json '
    ., (split(".") as $p | $big | getpath($p) | tojson)
' -Rr big.properties.service
cfg.keyload.backend.app.shutdown.timeout
"5s"
cfg.keyload.backend.app.jmx.enable
true
cfg.keyload.backend.app.jmx.nonexistent
null
cfg.nonexistent
null

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM