Как передать необработанную строку в переменную в Zsh? - PullRequest
0 голосов
/ 06 мая 2020

Мне нужно получить значение, связанное с ключом «версия», из файла JSON с jq или grep, независимо от того, не установлен ли первый. Я использую Zsh 5.7.1.

Файл JSON выглядит так:

{
    "version": "1.7.0+01e7dgc6",
    "date": "2020-04-06",
}

Таким образом, ожидаемый результат:

1.7.0+01e7dgc6

Вот мой сценарий с условным тестом, который передает регулярное выражение, которое, в свою очередь, передается в позиционный аргумент анонимной функции:

#!/usr/bin/env zsh
# Fetch silently JSON latest numeroted version with `jq` if installed; fallback to `grep` otherwise.
set -x
if dpkg -s 'jq' | grep -qF 'install ok installed'; then
    print "using jq"
    API="jq -r '.master.version'"
else
    print "falling back to grep"
    API="grep -Po '(?<="version": "\)\[\^"]*'"
fi

function {
    local JSON='path/to/URL/index.json'
    curl -fsSL "$JSON" | $@
} ${API}

Приведенный выше сценарий возвращает следующую ошибку (в режиме отладки):

+(anon):2> curl -fsSL path/to/the/URL/index.json
+(anon):2> 'jq -r '\''.master.version'\'
(anon):2: command not found: 'jq -r '.master.version'
curl: (23) Failed writing body (0 != 9320)

Вы можете видеть, что команда не найдена, потому что регулярное выражение было интерпретировано символами последовательности espace (например, 'jq -r' \ ''. Master.version '\' ). Вот почему мне нужны необработанные строки для правильного синтаксического анализа регулярного выражения в позиционном аргументе.

Та же самая ошибка обязательно возникает, когда тест терпит неудачу:

falling back to grep
+dpkg.zsh:9> API='grep -Po '\''(?<=version: )[^]*'\' 
...
+(anon):2> 'grep -Po '\''(?<=version: )[^]*'\'
(anon):2: command not found: grep -Po '(?<=version: )[^]*'
curl: (23) Failed writing body (0 != 9320)

Как я могу правильно проанализировать регулярное выражение НЕ экранируя символы, такие как одинарная кавычка (например, '), поскольку в Z Shell нет такого понятия, как механизм необработанных строк?

Возможно ли это с расширением параметров? Я пробовал их напрасно:

  • P flag (т.е. замена последовательности espace)
  • g: c (escape-последовательность процесса с опцией конкатенации)
  • e flag (выполняет расширение оболочки из одного слова)

или с квалификаторами подстановки? или, возможно, с модификаторами подстроки?

EDIT: Ты сделал мой день. Я благодарен как user1934428, так и chepner за вашу доброту.

1 Ответ

0 голосов
/ 08 мая 2020

zsh не выполняет разбиение слов при расширении параметров по умолчанию (и полагаться на него в любом случае будет подвержено ошибкам), поэтому вы передаете одиночный аргумент jq -r .master.version своему анонимному функция, а не 3 аргумента jq, -r и .master.version. Вместо этого используйте массив.

#!/usr/bin/env zsh
# Fetch silently JSON latest numeroted version with `jq` if installed; fallback to `grep` otherwise.
    if dpkg -s 'jq' | grep -qF 'install ok installed'; then
        print "using jq"
        API=(jq -r '.master.version')
    else
        print "falling back to grep"
        API=(grep -Po '(?<="version": "\)\[\^"]*')
    fi

function {
    local JSON='unified_resource_identifier/index.json'
    curl -fsSL "$JSON" | "$@"
} $API  # or "${API[@]}"

Кроме того, проще использовать whence, чтобы узнать, доступен ли jq вообще, чем проверять, был ли он установлен с dpkg специально.

if whence jq > /dev/null; then
  API=(jq -r '.master.version')
else
  API=(grep -Po '(?<="version": "\)\[\^"]*')
fi
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...