тл;др
$ var=1; cat <<EOF
"${var:+Hi there}"
${var:+$(printf %s '"Hi there"')}
EOF
"Hi there"
"Hi there"
Вышеприведенный пример демонстрирует два прагматичных обходных пути для включения двойных кавычек в альтернативное значение.
Подход со встроенным $(...)
более громоздкий, но более гибкий: он позволяет включать встроенные двойные кавычки, а также дает вам контроль над следует ли расширять значение или нет.
полезный ответ Йенса и Патрик Полезный ответ Обары проливает свет и дополнительно демонстрирует проблему.
Обратите внимание, что проблемное поведение в равной степени относится к:
(как отмечено в других ответах) обычные строки в двойных кавычках (например, echo "${var:+"Hi there"}"
; для 1-го обходного пути вам придется \
заключать в кавычки окружающие "
экземпляры, например, echo "\"${var:+Hi there}\""
; что любопытно, поскольку Gunstick указывает в комментарии к вопросу, используя \"
в альтернативном значении для получения "
в вывод действительно работает со строками в двойных кавычках — например, echo "${var:+\"Hi th\"ere\"}"
— в отличие от здесь-документов без кавычек.)
связанные расширения ${var+...}
, ${var-...}
/ ${var:-...}
и ${var=...}
/ ${var:=...}
Кроме того, есть связанная странность в отношении \
-обработки внутри альтернативных значений в двойных кавычках внутри строки в двойных кавычках / здесь-документа без кавычек: bash
и ksh
неожиданно удалить встроенные \
экземпляров; например,
echo "${nosuch:-"a\b"}"
неожиданно дает ab
, хотя echo "a\b"
отдельно дает a\b
- см. этот вопрос.
У меня нет объяснения такому поведению[1] , но я могу предложить практичные решения, которые работают со всеми основными POSIX-совместимыми оболочками (dash
, bash
, ksh
, zsh
):
Обратите внимание, что экземпляры "
никогда не нужны по синтаксическим причинам внутри альтернативного значения: альтернативное значение неявно обрабатывается как строка в двойных кавычках: no расширение с помощью тильды, разделение слов и подстановка не выполняются, но выполняется расширение параметров, арифметическое расширение и замена команд em>.
Обратите внимание, что в расширениях параметров, включающих замену или удаление префикса/суффикса, кавычки do имеют синтаксическое значение; например: echo "${BASH#*"bin"}"
или echo "${BASH#*'bin'}"
- любопытно, но dash
не поддерживает одинарные кавычки.
Если вы хотите заключить все альтернативное значение в кавычки, и оно не содержит встроенных кавычек, и вы хотите, чтобы оно расширялось,
процитируйте полное расширение, которое позволяет обойти проблему удаления "
из альтернативного значения:
# Double quotes
$ var=1; cat <<EOF
"${var:+The closest * is far from $HOME}"
EOF
"The closest * is far from /Users/jdoe"
# Single quotes - but note that the alternative value is STILL EXPANDED,
# because of the overall context of the unquoted here-doc.
var=1; cat <<EOF
'${var:+The closest * is far from $HOME}'
EOF
'The closest * is far from /Users/jdoe'
Для встроенных кавычек или для предотвращения расширения альтернативного значения
используйте подстановку встроенной команды ( без кавычек, хотя он будет вести себя так, как если бы он был заключен в кавычки):
# Expanded value with embedded quotes.
var=1; cat <<EOF
${var:+$(printf %s "We got 3\" of snow at $HOME")}
EOF
We got 3" of snow at /Users/jdoe
# Literal value with embedded quotes.
var=1; cat <<EOF
${var:+$(printf %s 'We got 3" of snow at $HOME')}
EOF
We got 3" of snow at $HOME
При необходимости эти два подхода можно комбинировать.
[1] Альтернативное значение:
- ведет себя как неявно строка в двойных кавычках,
'
, как и обычные строки в двойных кавычках, обрабатываются как литералы.
Учитывая вышеизложенное,
Было бы разумно рассматривать встроенные экземпляры "
также как литералы и просто передавать их, как и экземпляры '
.
Вместо этого, к сожалению, они удаляются em>, и если вы попытаетесь экранировать их как \"
, \
тоже сохранится (внутри не цитируемых здесь-документов, но, что любопытно, не внутри строк в двойных кавычках), за исключением ksh
— похвального исключения — , где \
экземпляра удалены. Любопытно, что в zsh
попытка использовать \"
полностью прерывает расширение (как и несбалансированные неэкранированные во всех оболочках).
- More specifically, the double quotes have no syntactic function in the alternative value, but they are parsed as if they did: quote removal is applied, and you can't use (unbalanced)
"
instances in the interior without \"
-escaping them (which, as stated, is useless, because the \
instances are retained).
Учитывая неявную семантику строки в двойных кавычках, литеральные экземпляры $
должны быть либо экранированы \$
, либо для встраивания строки в одинарных кавычках ($(printf %s '...')
) должна использоваться подстановка команд.
person
mklement0
schedule
13.12.2016
dq='"' ; ... ${var:+$dq}
- person choroba   schedule 06.12.2016${var:+$(echo '"')}
Но в принципе согласен. Есть что-то довольно странное в анализеword
в раскрытии параметров в кавычках (расширения параметров в здесь документах раскрываются так, как если бы они были в кавычках, согласно руководству, и, похоже, это так.) - person rici   schedule 07.12.2016echo "${var:+"Hi there"}"
в командной строке. Они возвращаются при использовании \, но документ HERE не является последовательным и выдает \ на выходе вместо . Что-то явно не так. - person Gunstick   schedule 08.12.2016