Улучшить `jq | @ base64` speed - PullRequest
0 голосов
/ 04 мая 2020

Примечание: Это упрощенная версия большого скрипта.

Реальные скрипты рекурсивно ищут сервер для s sh to, каждый .g[] (группа) может содержать больше groups и в конечном итоге будет содержать .s (серверный) объект, который содержит IP / имя / пользователя / et c ...

После отображения первых групп (что занимает слишком много времени) пользователя спрашивают, к какой группе он хочет «войти» или к какому серверу он хочет подключиться. (Серверы опущены для упрощения)


Рассмотрим следующий файл JSON;
{
    "g": [
        {
            "id": "1",
            "name": "Group - 1"
        },
        {
            "id": "2",
            "name": "Group - 2"
        },
        ...
        {
            "id": "10",
            "name": "Group - 10"
        }
    ]
}

Используя , я показываю пользователю каждый «вариант», представленный в .g[] array.

Исходя из этого поста, я использую следующий for-loop для итерации 'options';

for row in $(jq -r '.g[] | @base64' <<< $raw); do
    echo -e "${prefix}    $(_jq $row '.id')${hk}  $(_jq $row '.name')"
done


Проблема : скрипту требуется ~ 0.6 секунд, чтобы показать мне первые 10 записей;
$ time ./script
./script  0.61s user 0.09s system 101% cpu 0.685 total

Вопрос : Как улучшить скорость работы скрипта?


Некоторые неудачные попытки;
  • Пробовал реализовать следующий loop-logic, но, к сожалению, не смог заставить его работать с
  • Удаление | @base64 и base64 --decode приводит к тому, что l oop показывает каждую буквенную строку

#!/bin/bash
set -e

# Statics
_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )/"
red=`tput setaf 1`; green=`tput setaf 2`; yellow=`tput setaf 3`; blue=`tput setaf 4`; magenta=`tput setaf 5`; cyan=`tput setaf 6`; bow=`tput setaf 0;tput setab 7`; reset=`tput sgr0`; hk="${blue})${reset}"; undl=`tput smul`; bold=`tput bold`;

# getopts
P_DEBUG=false
while getopts "q: d" o; do
    case "${o}" in
        d) P_DEBUG=true ;;
    esac
done
shift $(($OPTIND - 1))

#
#       _jq
#       Decodes and search for json key/value
#       $1 --> json
#       $2 --> key
#
function _jq() {
    echo ${1} | base64 --decode | jq -r ${2}
}

# Validate & Read JSON
jq -e type ./json.json >/dev/null 2>&1 || echo -e 'Invalid JSON!'
raw=`jq . ./json.json`

# Search for server
reached_end=false
while [[ $reached_end == false ]]; do

    # Show id & name of each group
    for row in $(jq -r '.g[] | @base64' <<< $raw); do
        echo -e "${prefix}    $(_jq $row '.id')${hk}  $(_jq $row '.name')"
    done

    # Debug
    exit 22
done

1 Ответ

3 голосов
/ 04 мая 2020

Такой подход намного сложнее, чем действительно необходим. Делает ли это то, что вы хотели?

< json.json jq --arg prefix "${prefix}" --arg hk "${hk}" -r \
  '.g[] | "\($prefix)    \(.id) \($hk)  \(.name)"'

Это полностью заменяет for l oop одним вызовом jq, используя jq для форматирования строки вместо echo, исключая кодирование и декодирование base64 и устранение четырех вызовов подпроцесса на строку.

...