bash - 如何在 bash 中循环遍历 jq 唯一数组?

我正在尝试遍历唯一名称并提交来自 github json 对象的消息。但是,当数组中有空格时,bash 会将它们视为单独的数组项

#!/usr/bin/env bash

commits='[
  {
    "author": {
      "email": "email@example.com",
      "name": "Chris",
      "username": "chris"
    },
    "committer": {
      "email": "email@example.com",
      "name": "Chris",
      "username": "chris"
    },
    "message": "commit message 1"
  },
  {
    "author": {
      "email": "email@example.com",
      "name": "John",
      "username": "jdoe"
    },
    "committer": {
      "email": "email@example.com",
      "name": "John",
      "username": "jdoe"
    },
    "message": "commit message 2"
  },
    {
    "author": {
      "email": "email@example.com",
      "name": "John",
      "username": "jdoe"
    },
    "committer": {
      "email": "email@example.com",
      "name": "John",
      "username": "jdoe"
    },
    "message": "commit message 3"
  }
]'

authors=$( jq -rc '[.[].author.name] | unique | @sh' <<<"${commits}" )
echo "authors: $authors"

# this works
for author in $authors
do
  echo "author: $author"
done

echo "------------"

# this does not
messages=$( jq -rc '[.[].message] | unique | @sh' <<<"${commits}" )
echo "messages: $messages"

for message in $messages
do
  echo "message: $message"
done

哪些输出

authors: 'Chris' 'John'
author: 'Chris'
author: 'John'
------------
messages: 'commit message 1' 'commit message 2' 'commit message 3'
message: 'commit
message: message
message: 1'
message: 'commit
message: message
message: 2'
message: 'commit
message: message
message: 3'

虽然我期望:

authors: 'Chris' 'John'
author: 'Chris'
author: 'John'
------------
messages: 'commit message 1' 'commit message 2' 'commit message 3'
message: 'commit message 1'
message: 'commit message 2'
message: 'commit message 3'

最佳答案

使用 readarray (Bash 4+) 映射来自 jq 的空分隔输出:

#!/usr/bin/env bash

commits='[
  {
    "author": {
      "email": "email@example.com",
      "name": "Chris",
      "username": "chris"
    },
    "committer": {
      "email": "email@example.com",
      "name": "Chris",
      "username": "chris"
    },
    "message": "commit message 1"
  },
  {
    "author": {
      "email": "email@example.com",
      "name": "John",
      "username": "jdoe"
    },
    "committer": {
      "email": "email@example.com",
      "name": "John",
      "username": "jdoe"
    },
    "message": "commit message 2"
  },
    {
    "author": {
      "email": "email@example.com",
      "name": "John",
      "username": "jdoe"
    },
    "committer": {
      "email": "email@example.com",
      "name": "John",
      "username": "jdoe"
    },
    "message": "commit message 3"
  }
]'

readarray -d '' authors < <(jq -j '.[].author.name + "\u0000"' <<<"${commits}")

for author in "${authors[@]}"
do
  echo "author: $author"
done

echo "------------"

readarray -d '' messages < <(jq -j '.[].message + "\u0000"' <<<"${commits}")

for message in "${messages[@]}"
do
  echo "message: $message"
done

或者,如果您有没有 readarraymapfile 的旧 Bash 版本,您可以使用 ASCII 控制字符 ETX(End of TeXt 03) 并像这样使用 read:

IFS=$'\03' read -d '' -ra authors < <(jq -j '.[].author.name + "\u0003"' <<<"${commits}")

IFS=$'\03' read -d '' -ra messages < <(jq -j '.[].message + "\u0003"' <<<"${commits}")

也可以通过单个 jq 调用来填充两个数组:

# Populates both arrays from a single jq call
{
  IFS=$'\03' read -r -d '' -a authors
  IFS=$'\03' read -r -d '' -a messages
} < <(jq -j '([.[].author.name] | unique | .[] + "\u0003"), "\u0000",  ([.[].message] | unique | .[] + "\u0003")' <<<"${commits}")

解释:

  • [.[].author.name] |独一无二 | .[] + "\u0003":
    输出以 ETX (03) 分隔的唯一作者姓名列表。

  • "\u0000":插入空分隔符

  • [.[].message] |独一无二 | .[] + "\u0003":
    输出一个 ETX (03) 分隔的唯一消息列表。

  • jq 的全部输出提供给带有两个 read 命令的命令组。
    每次 read 都会在 null 分隔符或流的末尾停止。

{
  IFS=$'\03' read -r -d '' -a authors
  IFS=$'\03' read -r -d '' -a messages
}

https://stackoverflow.com/questions/60226618/

相关文章:

python - 如何在python中创建文件夹?

three.js - 如何使用 threejs 在 iPhone 上启用视网膜分辨率 render.

oracle - 在 Apex 中提交表单之前添加确认

list - 得到 "Fatal error: Index out of range": show

javascript - 如何模拟 axios.create([config]) 函数以返回其实例方

typescript - typescript 中的 bool 列表是否有 "all"或 "any"

ios - 从 XCode 的调试导航器中清除崩溃日志

node.js - Firebase 函数错误 : The default Firebase app

sql - 我如何允许sql中的重复值?

powershell - Terraform azurerm_virtual_machine_ext