【问题标题】:How to trim white space for every element in JQ?如何为 JQ 中的每个元素修剪空白?
【发布时间】:2017-06-13 16:15:51
【问题描述】:

我有以下简单的 JSON

json='[{"k1":" http://url", "k2":null, "k3":" v3", "k4":" v4"}]'

我需要的是:

"http://url",null

v1v2 之前没有空格)

我拥有的是:

echo $json | jq -c '.[] | .k1, .k2 ' | paste -d "," - -

如何去掉k1和k2值中的空格?

【问题讨论】:

  • 你有足够新的 jq 来拥有walk 功能吗?
  • 顺便说一句,echo $json 实际上有点错误——如果你的文本中有一个空格包围的*,它将被替换为文件名列表。比echo "$json"好多了。
  • @CharlesDuffy 我有最新的jq 版本。
  • 截至今天,最新的发布版本没有 walk——尽管它在 git 的主干构建中可用。
  • 替换echo "${json// }"之类的所有空格你满意吗?

标签: unix trim jq


【解决方案1】:

如果输入是 JSON 对象数组,并且您正在寻找单线,那么以下内容似乎满足您的要求:

jq '.[]|(.k1,.k2)|if type=="string" then gsub("^\\s+|\\s+$";"") else . end' | paste -d "," - -

根据您的输入,这将产生

"http://url",null

如果您对null 在输出中的显示方式很灵活,您还可以考虑使用全jq 解决方案(即不使用paste)。例如:

jq -r '.[]|[.k1,.k2]|map(if type=="string" then gsub("^\\s+|\\s+$";"") else . end)|@csv'

根据您的输入,这会产生:

"http://url",

【讨论】:

    【解决方案2】:

    以下内容将删除任意复杂 JSON 结构中任何位置的字符串中的前导和尾随空格:

    #!/usr/bin/env jq -cf
    
    # Define walk function (standard library only for jq 1.6 and newer, currently unreleased)
    def walk(f):
      . as $in
      | if type == "object" then
          reduce keys_unsorted[] as $key
            ( {}; . + { ($key):  ($in[$key] | walk(f)) } ) | f
      elif type == "array" then map( walk(f) ) | f
      else f
      end;
    
    walk(
      if type == "string" then
        (sub("^[[:space:]]+"; "") | sub("[[:space:]]+$"; ""))
      else . end
    )
    

    如果保存上述内容(例如,在trim-json 中),并将其标记为可执行(chmod +x trim-json),则./trim-json <<<"$json" 与您的给定输入发出:

    [{"k1":"v1","k2":"v2","k3":"v3","k4":"v4"}]
    

    同样,更新后的输入:

    $ json='[{"k1":" http://url", "k2":null, "k3":" v3", "k4":" v4"}]'
    $ ./trim-json <<<"$json"
    [{"k1":"http://url","k2":null,"k3":"v3","k4":"v4"}]
    

    【讨论】:

    • 您的解决方案效果很好,但我忘了提到一个新要求 - 它必须能够与 null 或空字符串 '' 或 URL 一起使用。我已经更新了问题。
    • @AdamSiemion, ...我使用更新的输入运行现有代码。如编辑中所示,它运行良好。 (有鉴于此,我很好奇您为什么会要求更改返回给我)。
    • @peak,感谢您的编辑。 (我会要求大多数人在 cmets 中提出建议,但您在这个主题上拥有足够的专业知识,我从未对您的更改感到不满意)。
    • @CharlesDuffy - 是的,我认为我们的波长差不多。如果您没有注意到,walk 的内置 def(今天!)已修改为使用 keys_unsorted。在这里更新 def 可能是个好主意....但这绝对是您的电话:-)
    • 感谢您的指点——我没有仔细观察上游并没有注意到这一点,在没有明确用户意图的情况下不改变顺序肯定是一种改进。
    【解决方案3】:

    该示例在每个值前面都有一个空格。对于您可以简单地删除字符串的第一个(或 N 个)字符的情况,则可以使用简单的映射范围切片:

    $ jq -c '.[] | map_values(.[1:]) | .k1,.k2' <<< "$json" | paste -d "," - -
    "http://url",null
    

    这种方法的好处是朴实无华且易于理解。

    【讨论】:

    • 这会去掉第一个字符,不管它是什么。如果不确定 每个 字符串都有前导空格,那……有点危险。
    猜你喜欢
    • 2023-02-15
    • 2012-04-09
    • 2010-11-14
    • 1970-01-01
    • 1970-01-01
    • 2022-11-16
    • 1970-01-01
    • 1970-01-01
    • 2018-08-26
    相关资源
    最近更新 更多