Что означает: $ {param: = value}?

34

Я прочитал следующее в Руководстве пользователя к Z-Shell :

Синонимом «true» является «:»; это часто используется в этой форме, чтобы дать аргументы, которые имеют побочные эффекты, но которые не должны использоваться - что-то вроде

: ${param:=value}

которая является общей идиомой во всех производных оболочки Борна. В расширении параметра $paramзадается значение value, если оно ранее было пустым, а в противном случае оставлено в покое. Так как это была единственная причина расширения параметра, вы :должны игнорировать аргумент. На самом деле, оболочка беспечно строит командную строку - двоеточие, за которым следует любое значение $param, независимо от того, произошло присвоение или нет, - затем выполняет команду; просто так получается, что ':' не замечает аргументов, которые ему были даны.

но я этого не понимаю Я понимаю, что это :означает true, но в выражении есть два двоеточия. В качестве второстепенного вопроса, почему эта идиома так часто используется во всех производных оболочки Борна? Какой цели это служит?

Примечание: меня интересует, что делает эта идиома как в bash, так и в zsh .

Благодарность

Амелио Васкес-Рейна
источник
Вы спрашиваете zshили bash?
энзотиб
@enzotib, мне интересны оба. Я уточнил это.
Амелио Васкес-Рейна

Ответы:

31

Давайте разберем это на части.

Этот код запускает команду :с некоторыми аргументами. Команда :ничего не делает и игнорирует свои аргументы. Поэтому вся командная строка ничего не делает, кроме каких-либо побочных эффектов, возникающих в аргументах.

Синтаксис ${parameter_name:=value}существует во всех неантикварных оболочках в стиле Борна, включая ash, bash, ksh и zsh. При необходимости он устанавливает значение по умолчанию. Это эквивалентно

if [ -z "$parameter_name" ]; then parameter_name=value; fi
 ${parameter_name}

Другими словами, если parameter_nameне установлено или установлено пустое значение, то установите его на указанное значение; и затем выполните команду, используя новое значение параметра. Существует вариант, ${parameter_name=value}который оставляет параметр пустым, если он был пустым, используя только указанное значение, если параметр был не установлен.

Этот синтаксис описан в разделе «Расширение параметров» в спецификации POSIX , а также в руководствах по dash, bash, ksh и zsh.

Существуют варианты этого синтаксиса, в частности, ${parameter_name:-value}которые позволяют использовать значение по умолчанию только для этого расширения, без назначения параметра.

В итоге, : ${parameter_name:=value}это краткий способ написания

if [ -z "$parameter_name" ]; then parameter_name=value; fi
Жиль "ТАК - перестань быть злым"
источник
11

:не означает «правда» - вы, вероятно, думаете об этом while :, но даже в этом выражении это не означает «правда», это просто происходит с оценкой (на самом деле, это просто нулевая команда или noop).

Этот параметр extension ( ${x:=y}) означает «назначить y для x, если x не установлен или пуст, и расширить до y ».

$ echo "${foo:=bar}"
bar
$ foo=baz
$ echo "${foo:=bar}"
baz
$ foo=
$ echo "${foo:=bar}"
bar
$ echo "${foo}"
bar

В вики Bash Hackers есть хорошая статья о расширении параметров здесь .

Причиной этого :является то, что в то время как другие части команды оцениваются, они не выполняются (как :нулевая команда). Таким образом, вы ${x:=y}выполняете его функцию, не влияя ни на что другое, например, если у вас его нет :в начале, он попытается выполнить команду с именем y .

Вот bashсправочная страница ::

:: :
    Null command.

    No effect; the command does nothing.

    Exit Status:
    Always succeeds.
Крис Даун
источник
3

Первая :- это команда, она называется «noop» или «no operation». Как сказано в справочной странице, он часто используется для оценки аргументов.

Второй :- это квалификатор в расширении переменной - технически это так :=. Который, как сказано, устанавливает значение, если оно не имеет значения.

В смысле, если вам нужно значение переменной среды по умолчанию, вы можете использовать этот синтаксис. Например, при запуске программы cron(8)среда не устанавливается, а точечные файлы оболочки не запускаются. Поэтому вам может потребоваться установить некоторые значения по умолчанию.

: ${JAVA_HOME:=/usr/local/jdk-1.6.0_28}

Затем вы можете «установить и забыть» (пока не изменится jvm по умолчанию).

Arcege
источник