gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-05 08:39:17 27 4
gpt4 key购买 nike

我正在尝试遍历唯一名称并提交来自 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
}

关于bash - 如何在 bash 中循环遍历 jq 唯一数组?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60226618/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com