Используйте 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
В качестве альтернативы, если у вас есть более старая версия Bash без readarray
или mapfile
Вы можете отделить строки с помощью управляющего символа ASCII ETX (Конец 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] | unique | .[] + "\u0003"
:
Вывести список уникальных авторов с разделителями ETX (03)
.
"\u0000"
: вставить нулевой разделитель
[.[].message] | unique | .[] + "\u0003"
:
Вывести список уникальных сообщений с разделителями ETX (03)
.
Подает весь вывод jq
в группу команд с двумя командами read
.
Каждая read
останавливается на нулевом разделителе или конце потока.
{
IFS=$'\03' read -r -d '' -a authors
IFS=$'\03' read -r -d '' -a messages
}