как проверить существование переменных и сравнить со строкой в ​​busybox?

Я хочу использовать что-то подобное

if [[ ! -z "$ENV" && $ENV == 'production' ]]; then echo "production"; else echo "dev"; fi 

но в BusyBox это не работает 🙁

 sh: 1: [[: not found 

Похоже, что любая комбинация AND или OR не работает в IF-заявлении в busybox

    Вы можете использовать более старый синтаксис

     if [ -n "$ENV" -a "$ENV" = 'production' ] 

    (обратите внимание, что я использовал -n а не ! -z потому что он читается легче, но это то же самое).

    Или мы можем упростить еще более старый синтаксис, заставив строку иметь значение:

     if [ "x$ENV" = 'xproduction' ] 

    Наконец, тест -n может не понадобиться, и вы можете просто сделать

     if [ "$ENV" = 'production' ] 

    [[...]] – это конструкция оболочки Korn, также поддерживаемая bash и zsh но в остальном не стандартная sh (и не поддерживается какой-либо другой оболочкой).

    busybox sh основан на ash которая реализует подмножество спецификации POSIX sh (в локали POSIX, она по большей части совместима) с очень небольшим количеством расширений и, в частности, не с этим.

    В любом случае при написании сценария sh вы должны придерживаться спецификации POSIX sh . Скрипты, которые используют [[...]] должны явно ссылаться на ksh , bash или zsh . bash также в основном совместима с POSIX sh, но с гораздо большим количеством расширений (включая этот).

    Тестирование для x непустое, а затем равное production имеет мало смысла. Если x == production , то, очевидно, оно не пустое.

    Выполняйте строковые сравнения с оболочкой POSIX и утилитами, у вас есть несколько вариантов, наиболее очевидными в этом случае являются:

    • [ утилита aka test , обычно встроенная в оболочку:

       if [ "$var" = production ]; then echo PROD fi 
    • конструкция case :

       case $var in production) echo PROD;; "") echo EMPTY;; *) echo non-PROD;; esac 

    Теперь вы можете проверить, что переменная установлена (в отличие от непустого), до разыменования ее, в случае, когда nounset опция nounsetset -u или set -o nounset или с #! /bin/sh -u в качестве строки she-bang), так как в противном случае [ "$ENV" = production ] приведет к завершению работы оболочки, если $ENV не был установлен. Для этого вам нужно:

     if [ "${var+set}" = set ] && [ "$var" = production ]; then echo PROD fi 

    (вам следует избегать оператора -a [ AND, поскольку он устарел и ненадежен).

    Хотя лучший и более канонический способ сделать это:

     if [ "${var-}" = production ]; then echo PROD fi 

    nounset не запускается при расширении ${var+string} или ${var-string} . ${var-} расширяется до содержимого переменной $var если переменная установлена ​​или пустая строка в противном случае.

    Несколько других примечаний:

    $ENV – специальная переменная для sh . Когда он запускается в интерактивном режиме, он берется как путь к файлу для чтения инициализации (эквивалент ~/.bashrc для bash ). Вы не должны использовать его для других целей.

    Вы обнаружите, что некоторые старые публикации сценариев оболочки Unix рекомендуют использовать [ "x$var" = xproduction ] или [ production = "x$var" ] для сравнения строк. Это было для устранения ошибок в некоторых старых версиях [ и test утилиты, которая была смущена некоторыми значениями $var like ! , ( или -n . Он не нужен в современных системах, но что-то нужно учитывать для очень старых систем. В любом case конструкция case не имеет такой проблемы.

    Другие утилиты POSIX, которые могут выполнять сравнение строк, включают expr и awk .

      awk_equal() { awk 'BEGIN{exit(!(""ARGV[1] == ""ARGV[2]))}' "$1" "$2"; } expr_equal() { expr "x $1" = "x $2" > /dev/null; } if awk_equal "$var" production; then echo PROD fi if expr_equal "$var" production; then echo PROD fi 

    Обратите внимание на необходимость добавления "" к значениям с awk чтобы убедиться, что мы получаем сравнение строк (иначе 1 будет считаться равным 01 или 1e0 ) и x в expr по той же причине, но также и для предотвращения проблем со значениями expr операторы.

    Как с awk и с expr (по крайней мере POSIXly), они не являются операторами равенства, а являются проверкой того, имеют ли два операнда одинаковый порядок сортировки, что необязательно может быть одним и тем же. Например, в expr_equal ② ③ system expr_equal ② ③ возвращает true, потому что ни ②, ни ③ не имеют определенного порядка сортировки. Некоторые awk реализации, такие как gawk , mawk и busybox awk игнорируют это требование POSIX и вместо этого выполняют простое сравнение между байтами.

    В любом случае, я не могу придумать какой-либо веской причины, по которой вы бы предпочли бы, чтобы это было выше или здесь.