【问题标题】:Get json field value with JQ from different directory使用 JQ 从不同目录获取 json 字段值
【发布时间】:2016-12-29 15:26:27
【问题描述】:

标题可能不正确,因为我实际上不确定这是失败的地方。我有一个在一个目录中运行的 bash 脚本,以及一个我需要来自不同目录的值的 JSON 文件。我想将外部目录中的值复制到当前目录中相同的 JSON 文件中。

我正在使用 jq 来获取值,但我不知道如何从脚本运行所在目录之外的目录中获取值。

文件结构的相关位如下;

cloudformation
  - parameters_v13.json
environment_files
  - prepare_stack_files.json (the script this is run from)
  - directory, changes based on where the script is pointed
      - created directory where created files are being output
         - GREPNAME_parameters.json

我感兴趣的 JSON 文件块如下所示;

[ 
{
   "ParameterKey": "RTSMEMAIL",
   "ParameterValue": "secretemail"
  }
]

脚本需要从cloudformation/parameters_v13.json 获取“秘密邮件”并将其粘贴到GREPNAME_parameters.json 文件中匹配的RTSMEMAIL 字段中。

我一直在尝试以下操作,但没有成功 - 没有任何输出。也没有错误消息,只是空白输出。我知道 GREPNAME 路径是正确的,因为它在其他地方使用没有问题。

jq --arg email "$EMAIL" '(.[] | select(.ParameterKey == "RTSMEMAIL") | .ParameterValue) |= $email' ../cloudformation/parameters_v13.json | sponge ${GREPNAME}_parameters.json

【问题讨论】:

  • 您的输入无法验证,如果您能提供完整的json 或示例文件,将会很有帮助。
  • 对,对不起,把括号放在里面,这样它就可以算作一个完整的文件了
  • 你对jq --arg email "$EMAIL" '(.[] | select(.ParameterKey == "RTSMEMAIL") | .ParameterValue) |= $email'有什么期望,它给了我空白输出。
  • 我期待secretemail - 空白输出正是我难过的原因。

标签: bash jq


【解决方案1】:

这个jq 过滤器应该可以帮助你获得secretmail 字符串

jq '.[] | select(.ParameterKey=="RTSMEMAIL") | .ParameterValue' json
"secretemail"

为原始输出添加 -r 文件以删除值周围的引号

jq -r '.[] | select(.ParameterKey=="RTSMEMAIL") | .ParameterValue' json
secretemail

--原始输出/-r:

使用此选项,如果过滤器的结果是字符串,那么它将直接写入标准输出,而不是格式化为带引号的 JSON 字符串。这对于让 jq 过滤器与非基于 JSON 的系统对话很有用。

正如我所见,您正在尝试将args 传递给jq 过滤器,对于提取,您可以先通过在bash 中设置变量来做一些事情

email="RTSMEMAIL"

现在将其传递给过滤器

jq --arg email "$email" -r '.[] | select(.ParameterKey==$email) | .ParameterValue' json 
secretemail

现在要将从parameters_v13.json 文件中获得的字符串替换为您的GREPNAME_parameters.json,请执行以下步骤:-

首先将第一个文件的结果存储在一个变量中以供以后重复使用,我使用该文件提取为json,这实际上将您的parameters_v13.json文件指向另一个路径。

replacementValue=$(jq --arg email "$email" -r '.[] | select(.ParameterKey==$email) | .ParameterValue' json)

现在$replacementValue 将保存您要更新到另一个文件的secretmail。正如您之前指出的那样,GREPNAME_parameters.json 的语法与第一个文件类似。像下面这样,

$ cat GREPNAME_parameters.json
[ 
{
   "ParameterKey": "SOMEJUNK",
   "ParameterValue": "somejunkvalue"
  }
]

现在我了解您的意图是将上述文件中的"ParameterValue" 替换为从另一个文件中获得的值。为此,

jq --arg replace "$replacementValue" '.[] | .ParameterValue = $replace' GREPNAME_parameters.json
{
  "ParameterKey": "SOMEJUNK",
  "ParameterValue": "secretemail"
}

然后您可以将此输出写入临时文件并将其作为GREPNAME_parameters.json 移回。希望这能回答您的问题。

【讨论】:

  • 我很欣赏这个答案,但它实际上并没有解决我的问题,即我试图从一个文件中选择值并将其移动到另一个文件中。问题不在于价值,而在于路径。
  • @Alex:你想把这个值提供给另一个命令是你打算做的吗?
  • 简而言之,我想将parameters_v13.json文件中的秘密邮件复制到`GREPNAME_parameters.json文件中。
  • 如何将字符串复制到另一个文件? @Alex,写吗?在末尾追加?
  • 我是 bash / jq 的超级新手,所以这就是我难过的地方。我想我可以使用我所做的命令从 v13 文件中提取值,然后将其海绵到 grepname 文件中,但这似乎不起作用。如果您知道其他方式,请告诉我。
【解决方案2】:

@亚历克斯-

(1) sponge 只是提供了一种方便的方式来修改文件,而无需管理临时文件。你可以这样使用它:

jq  ........ input.json | sponge input.json

这里,“input.json”是您要“就地”编辑的文件。如果你想避免覆盖输入文件,你不会使用sponge。事实上,在您完全确定这是您想要的之前,我建议您不要这样做。

(2) 有几种策略可以使用 jq 实现您所描述的内容。它们基本上分为两类: (a) 调用 jq 两次; (b) 调用 jq 一次。

忽略sponge 部分:

  • 两次使用 jq 的模式如下:

    param=$(jq -r '.[]
      | select(.ParameterKey == "RTSMEMAIL")|.ParameterValue
      ' cloudformation/parameters_v13.json )
    
    jq --arg param "$param" -f edit.jq input.json
    
  • 假设您拥有 jq 1.5,只需调用一次 jq 即可完成所有操作的模式是:

    jq --argfile p cloudformation/parameters_v13.json -f manage.jq input.json
    

这里,edit.jq 和 manage.jq 是包含合适的 jq 程序的文件。

根据我对您要求的理解,edit.jq 可能如下所示:

(.[] | select(.ParameterKey == "RTSMEMAIL")|.ParameterValue) |= $param

manage.jq 可能如下所示:

($p[] | select(.ParameterKey == "RTSMEMAIL")|.ParameterValue) as $param
| (.[]| select(.ParameterKey == "RTSMEMAIL")|.ParameterValue) |= $param

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-07
    • 2017-02-09
    • 1970-01-01
    • 2019-04-11
    相关资源
    最近更新 更多