【问题标题】:How to use a capture variable as a field name in JQ?如何在 JQ 中使用捕获变量作为字段名?
【发布时间】:2020-12-02 16:10:50
【问题描述】:

我正在尝试使用 jq 自动将 i18n 字符串文件从一个库采用的格式更改为另一个。

我有一个如下所示的 json 文件:

{
  "some_label": {
    "message": "a string in English with a $VARIABLE$",
    "description": "directions to translators",
    "placeholders": {
      "VARIABLE": {
        "content": "{variable}"
      }
    }
  },
  // more of the same...
}

我需要把它转给"some-label": "a string in English with a {variable}"

我已经很接近了。目前,我正在使用

jq '[.                                                                                                                                                                            
    | to_entries 
    | .[] 
    | .key |= (gsub("_";"-")) 
    |  .value.placeholders as $p 
    | .value.message |= (sub("\\$KEY_NAME\\$";$p.KEY_NAME.content)) 
    | .value = .value.message
   ] | from_entries'

下一步是在sub 调用中使用捕获组,这样我就可以以编程方式获取具有不同名称的变量,但我不确定如何使用捕获组来索引$p

我尝试了sub("\\$(?<id>VARIABLE)\\$";$p.(.id).content),它给出了一个编译器错误,我几乎不知道下一步该尝试什么。

【问题讨论】:

  • 这只是一个示例,用于显示它所属的较大 JSON 值的架构。我将示例更新为更明确

标签: regex jq pcre


【解决方案1】:

这是实现预期结果的一种方法。它也可以进一步简化。在顶层,它通过将整个过滤器封闭在with_entries() 下并根据需要修改.value 字段来删除to_entries/from_entries 的使用

with_entries(
  .key |= ( gsub("_";"-") )  |
  .value.placeholders as $p  |
  .value.message as $m       |
  ( $m | match(".*\\$(.*)\\$") | .captures[0].string ) as $c |
  ( $p | .[$c].content ) as $v |
  ( "\\$" + $c + "\\$" ) as $t     |
  .value = ( $m | sub($t; $v) )
)

我对表达式关键部分的看法是

  1. $m | match(".*\\$(.*)\\$") | .captures[0].string 部分进行正则表达式匹配以提取$..$ 中的部分.message
  2. $p | .[$c].content 部分使用$c 的动态值进行通用对象索引提取
  3. 由于sub()/gsub()函数的第一个参数是一个正则表达式,捕获的值$c需要创建为\\$VARIABLE\\$

jqplay - Demo

【讨论】:

  • 这只会输出 JSON 中的最后一个条目。看到$p | .[$c].content 是我一直在寻找的!我会继续处理一般情况——我还需要处理多个变量
  • 不用等待——我认为它只选择有变量的条目——有些没有
  • @JonCohen:我尝试根据提供的输入回答您的问题。它的工作原理与您所需的输出中显示的完全一样。如果有更复杂的例子,你应该事先更新它
  • 我并不是要贬低您的回复!我只是想要你给我的这一步的帮助。感谢您的帮助!
【解决方案2】:

这是一个基本的 JQ。没有尝试过复杂的输入,也没有适应$。我想你可以在此基础上构建 -

to_entries | map(. as $kv | { "\($kv.key)": $kv.value.placeholders | to_entries | map(. as $p | $kv.value.message | sub("\\$\($p.key)\\$"; $p.value.content))[0]}) | add 

输出 -

{
  "some_label": "a string in English with a {variable}"
}

【讨论】:

  • @Inian 我知道。 OP 不应该在此之上构建而不是提供整个解决方案吗?我可以更改对评论的回答。目标是显示变量替换。
  • 我已更新我的答案以更好地符合 OP 的期望。
猜你喜欢
  • 1970-01-01
  • 2013-06-07
  • 1970-01-01
  • 1970-01-01
  • 2017-01-07
  • 1970-01-01
  • 1970-01-01
  • 2012-08-14
  • 1970-01-01
相关资源
最近更新 更多