Использование â € œ $ {a: -b} â для присвоения переменной в скриптах

Я рассматривал несколько сценариев, написанных другими людьми (в частности, Red Hat), и многие их переменные назначаются с использованием следующей записи VARIABLE1="${VARIABLE1:-some_val}" или некоторые расширяют другие переменные VARIABLE2="${VARIABLE2:-`echo $VARIABLE1`}"

В чем смысл использования этой нотации вместо простого объявления значений непосредственно (например, VARIABLE1=some_val)?

Есть ли преимущества для этой нотации или возможных ошибок, которые могут быть предотвращены?

В этом контексте имеет значение :-?

290 голосов | спросил Rothgar 3 AMpThu, 03 Apr 2014 04:13:32 +040013Thursday 2014, 04:13:32

3 ответа


461

Этот метод позволяет присваивать переменной значение, если другая переменная является пустой или не определена. ПРИМЕЧАНИЕ. Эта «другая переменная» может быть той же или другой переменной.

Отрывок

${parameter:-word}
    If parameter is unset or null, the expansion of word is substituted. 
    Otherwise, the value of parameter is substituted.

ПРИМЕЧАНИЕ: Эта форма также работает, ${parameter-word}. Если вы хотите увидеть полный список всех форм расширения параметров, доступных в Bash, я настоятельно рекомендую вам взглянуть на эту тему в вики Bash Hacker под названием « Расширение параметров ".

Примеры

переменная не существует
$ echo "$VAR1"

$ VAR1="${VAR1:-default value}"
$ echo "$VAR1"
default value
существует
$ VAR1="has value"
$ echo "$VAR1"
has value

$ VAR1="${VAR1:-default value}"
$ echo "$VAR1"
has value

То же самое можно сделать, оценив другие переменные или выполнив команды в пределах значения по умолчанию для обозначения нотации.

$ VAR2="has another value"
$ echo "$VAR2"
has another value
$ echo "$VAR1"

$

$ VAR1="${VAR1:-$VAR2}"
$ echo "$VAR1"
has another value

Дополнительные примеры

Вы также можете использовать несколько другую нотацию, где это просто VARX=${VARX-<def. value>}

$ echo "${VAR1-0}"
has another value
$ echo "${VAR2-0}"
has another value
$ echo "${VAR3-0}"
0

В приведенном выше $VAR1 & $VAR2 уже были определены с строкой «имеет другое значение», но $VAR3 не определено, поэтому вместо этого использовалось значение по умолчанию 0.

Другой пример

$ VARX="${VAR3-0}"
$ echo "$VARX"
0

Проверка и назначение с помощью обозначения :=

Наконец, я упомянул удобный оператор, :=. Это проверит и назначит значение, если тестируемая переменная пуста или неопределена.

Пример

Обратите внимание, что теперь установлен $VAR1. Оператор := выполнил тест и назначение за одну операцию.

$ unset VAR1
$ echo "$VAR1"

$ echo "${VAR1:=default}"
default
$ echo "$VAR1"
default

Однако, если значение установлено ранее, то оно остается в покое.

$ VAR1="some value"
$ echo "${VAR1:=default}"
some value
$ echo "$VAR1"
some value

Справочная таблица Handy Dandy

    ss of table

Ссылки

ответил slm 3 AMpThu, 03 Apr 2014 04:39:41 +040039Thursday 2014, 04:39:41
15

@slm уже включил документы POSIX - которые очень полезны - но они действительно не расширяются, как эти параметры могут быть объединены, чтобы влиять друг на друга. Здесь еще нет упоминания об этой форме:

${var?if unset parent shell dies and this message is output to stderr}

Это выдержка из еще один ответ , и я думаю, что он очень хорошо демонстрирует, как это работает:

    sh <<-\CMD
    _input_fn() { set -- "[email protected]" #redundant
            echo ${*?WHERES MY DATA?}
            #echo is not necessary though
            shift #sure hope we have more than $1 parameter
            : ${*?WHERES MY DATA?} #: do nothing, gracefully
    }
    _input_fn heres some stuff
    _input_fn one #here
    # shell dies - third try doesnt run
    _input_fn you there?
    # END
    CMD
heres some stuff
one
sh: line :5 *: WHERES MY DATA?

Другой пример из

В приведенном выше примере используются все четыре формы подстановки параметров POSIX и их различные sh <<-\CMD N= #N is NULL _test=$N #_test is also NULL and v="something you would rather do without" ( #this subshell dies echo "v is ${v+set}: and its value is ${v:+not NULL}" echo "So this ${_test:-"\$_test:="} will equal ${_test:="$v"}" ${_test:+${N:?so you test for it with a little nesting}} echo "sure wish we could do some other things" ) ( #this subshell does some other things unset v #to ensure it is definitely unset echo "But here v is ${v-unset}: ${v:+you certainly wont see this}" echo "So this ${_test:-"\$_test:="} will equal NULL ${_test:="$v"}" ${_test:+${N:?is never substituted}} echo "so now we can do some other things" ) #and even though we set _test and unset v in the subshell echo "_test is still ${_test:-"NULL"} and ${v:+"v is still $v"}" # END CMD v is set: and its value is not NULL So this $_test:= will equal something you would rather do without sh: line 7: N: so you test for it with a little nesting But here v is unset: So this $_test:= will equal NULL so now we can do some other things _test is still NULL and v is still something you would rather do without или :colon null . Дополнительная информация приведена в ссылке выше, и здесь она снова .

Еще одна вещь, которую люди часто не считают о not null, - это то, как очень полезно она может быть в документе здесь. Вот еще один отрывок из другого ответа :

TOP

Здесь вы установите некоторые значения по умолчанию и подготовьтесь распечатать их при вызове ...

${parameter:+expansion}

СРЕДНЯЯ

Здесь вы определяете другие функции для вызова функции печати на основе их результатов ...

#!/bin/sh
    _top_of_script_pr() ( 
        IFS="$nl" ; set -f #only split at newlines and don't expand paths
        printf %s\\n ${strings}
    ) 3<<-TEMPLATES
        ${nl=
}
        ${PLACE:="your mother's house"}
        ${EVENT:="the unspeakable."}
        ${ACTION:="heroin"}
        ${RESULT:="succeed."}
        ${strings:="
            I went to ${PLACE} and saw ${EVENT}
            If you do ${ACTION} you will ${RESULT}
        "}
    #END
    TEMPLATES

НИЖНИЙ

У вас есть все настройки сейчас, так что вот где вы будете выполнять и вытащить ваши результаты.

    EVENT="Disney on Ice."
    _more_important_function() { #...some logic...
        [ $((1+one)) -ne 2 ] && ACTION="remedial mathematics"
            _top_of_script_pr
    }
    _less_important_function() { #...more logic...
        one=2
        : "${ACTION:="calligraphy"}"
        _top_of_script_pr
    }

Результаты

Я расскажу, почему в одно мгновение, но выполнение приведенного выше результата дает следующие результаты:

  

_less_important_function : "${PLACE:="the cemetery"}" _more_important_function : "${RESULT:="regret it."}" _less_important_function первый запуск:

     
    

Я пошел в дом твоей матери и увидел Дисней на льду.

         

Если вы выполните каллиграфию , вы добьетесь успеха.

  
     

то _less_important_function()'s

     
    

Я пошел на кладбище и увидел Disney on Ice.

         

Если вы выполняете исправление математики , вы добьетесь успеха.

  
     

_more_important_function(): :

     
    

Я пошел на кладбище и увидел Диснея на льду.

         

Если вы исправляете математику, вы будете сожалеть об этом.

  

КАК ЭТО РАБОТАЕТ:

Ключевой особенностью здесь является концепция расширения _less_important_function() Вы можете установить переменную в значение только в том случае, если она не установлена ​​или имеет значение null, используя форму

  
    

conditional ${parameter} expansion. : = ${var_name

  

Если вместо этого вы хотите установить только отмененную переменную, вы должны опустить desired_value} , а нулевые значения останутся как есть.

ON SCOPE:

Возможно, вы заметили, что в приведенном выше примере :colon и $PLACE изменится при установке через $RESULT , хотя parameter expansion уже вызывается, предположительно устанавливая их при запуске. Причина этого в том, что _top_of_script_pr() - это функция _top_of_script_pr() - я заключил ее в ( subshelled ) , а не parens , используемые для других. Поскольку он вызывается в подоболочке, каждая переменная, которую он устанавливает, является { curly braces } , и по мере ее возвращения в родительскую оболочку эти значения исчезают.

Но когда locally scoped устанавливает _more_important_function() , это $ACTION , поэтому он влияет на globally scoped вторую оценку _less_important_function()'s , потому что $ACTION устанавливает _less_important_function() только через $ACTION

ответил mikeserv 3 AMpThu, 03 Apr 2014 11:39:45 +040039Thursday 2014, 11:39:45
6

Личный опыт.

Я использую этот формат иногда в своих сценариях, чтобы делать ad-hoc чрезмерное превышение значений, например. если у меня есть:

$ cat script.sh
SOMETHING="${SOMETHING:-something}"; echo "$SOMETHING"; 

Я могу запустить:

$ env SOMETHING="something other than the default value" ./script.sh` 

, не изменяя исходное значение по умолчанию SOMETHING.

ответил h.j.k. 3 AMpThu, 03 Apr 2014 10:09:44 +040009Thursday 2014, 10:09:44

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132