Разбор JSON с помощью инструментов BusyBox

419
Josh Habdas

У меня есть POSIX-совместимый установочный скрипт, который определяет последнюю версию какого-либо программного обеспечения путем извлечения информации из BLOB-объекта json, полученного из реестра программного обеспечения:

meta=$(wget -qO - https://registry.npmjs.org/after-dark/latest) grep --version | grep "BSD grep" 1>/dev/null && vers=$(echo "$meta" | grep -oE '"version":(\d*?,|.*?[^\\]",)' | tr -d 'version": ,') grep --version | grep "GNU grep" 1>/dev/null && vers=$(echo "$meta" | grep -oP '"version":(\d*?,|.*?[^\\]",)' | tr -d 'version": ,') 

Мне нужно сделать это программное обеспечение совместимым с BusyBox, который, как и BSD grep, использует -Eдля расширенной поддержки регулярных выражений. Однако он не поддерживает --versionфлаг.

Если я запускаю, busybox grepя вижу версию busybox. Должен ли я просто использовать это, чтобы добавить совместимость? Есть ли лучший способ, которым я мог бы сделать это, чтобы удалить запах кода без установки зависимостей.

-1
В более общем случае можно попытаться определить распределение и затем использовать правильный синтаксис для двоичного файла `grep`: https://unix.stackexchange.com/questions/6345/how-can-i-get-distribution-name-and -version-number-in-a-simple-shell-script - также попытаться использовать абсолютные пути к `/ bin / grep`. slhck 5 лет назад 0
ИМХО, вы уже ответили на свой вопрос, - используйте `busybox`` grep`. Это будет согласованно на разных платформах. Единственное, что `busybox` не установлен по умолчанию на всех системах. Другой подход заключается в использовании `awk` для синтаксического анализа, он поставляется практически со всеми системами на основе Unix по умолчанию, даже на урезанных платформах, просто используйте только совместимые команды awk, которые существуют во всех его разновидностях (classic awk, nawk, gawk ... ), это было бы гораздо более портативным. Alex 5 лет назад 1
Спасибо, Алекс. [Этот ответ] (https://stackoverflow.com/a/23454288/712334) в SO предоставляет некоторую историю, касающуюся добавления PCRE к grep, который предшествует POSIX, и, следовательно, ваше предложение использовать `awk` для лучшей переносимости будет принимая во внимание. Кажется, корень проблемы, однако, может быть либо ошибкой, либо недокументированной возможностью в BSD grep при использовании расширенного регулярного выражения, как это было предложено [здесь] (https://stackoverflow.com/q/23454172/712334). Josh Habdas 5 лет назад 0

1 ответ на вопрос

0
Josh Habdas

Не могу больше ждать, поэтому я добавил несколько свежих идей и нашел следующее решение, которое хорошо зарекомендовало себя с использованием GNU, BSD и BusyBox grep и улучшает поддержку semver:

egrep -o "\"version\".*[^,]*," <<< "$meta" | cut -d ',' -f1 | cut -d ':' -f2 | tr -d '" ' 

Он работает, вызывая ERE grep с регулярным выражениемнаконечником шляпы ) и использует, cutчтобы :вырезать запятую, взять все в правой части, обрезать строку и удалить все присутствующие двойные кавычки.

Данное $metaиз {"version":"5.5.0-beta4",}вернется точно 5.5.0-beta4.
Данное $metaиз "version" : 1,вернется точно 1.

Предполагается, что versionполе не является последним полем в BLOB-объекте JSON, что является компромиссом для удобочитаемости.

Применительно к исходному вопросу результат:

vers=$(echo "$meta" | egrep -o "\"version\".*[^,]*," | cut -d ',' -f1 | cut -d ':' -f2 | tr -d '" ') 

Устранение необходимости обнаружения версии grep и удаление запаха кода.

ОБНОВИТЬ:

Я был в конечном счете, привел к более элегантному решению, используя sedв последующем вопросе на SO.