В моей среде Bash я использую переменные, содержащие пробелы, и я использую эти переменные в подстановке команд. К сожалению, я не могу найти ответ на SE.
Как правильно указать мои переменные? И как мне это сделать, если они вложенные?
DIRNAME=$(dirname "$FILE")
или я цитирую вне подстановки?
DIRNAME="$(dirname $FILE)"
или оба?
DIRNAME="$(dirname "$FILE")"
или я использую обратные галочки?
DIRNAME=`dirname "$FILE"`
Как правильно это сделать? И как я могу легко проверить, правильно ли указаны кавычки?
bash
shell
quoting
command-substitution
CousinCocaine
источник
источник
Ответы:
В порядке от худшего к лучшему:
DIRNAME="$(dirname $FILE)"
не будет делать то, что вы хотите, если$FILE
содержит пробелы или символы Globbing\[?*
.DIRNAME=`dirname "$FILE"`
технически правильно, но для расширения команд не рекомендуется использовать обратные галочки из-за дополнительной сложности при их вложении.DIRNAME=$(dirname "$FILE")
правильно, но только потому, что это задание . Если вы используете подстановку команд в любом другом контексте, например,export DIRNAME=$(dirname "$FILE")
илиdu $(dirname "$FILE")
, отсутствие кавычек вызовет проблемы, если в результате раскрытия будут использованы пробелы или символы-заглушки.DIRNAME="$(dirname "$FILE")"
это рекомендуемый способ. Вы можете заменитьDIRNAME=
командой и пробелом, не меняя ничего другого, иdirname
получите правильную строку.Чтобы улучшить еще дальше:
DIRNAME="$(dirname -- "$FILE")"
работает, если$FILE
начинается с тире.DIRNAME="$(dirname -- "$FILE"; printf x)" && DIRNAME="${DIRNAME%?x}"
работает, даже если$FILE
заканчивается новой строкой, так как$()
обрезает новые строки в конце вывода иdirname
выводит новую строку после результата. Блинdirname
, почему ты должен быть другим?Вы можете вкладывать расширения команд сколько угодно. С
$()
вами всегда создается новый контекст цитирования, поэтому вы можете делать такие вещи:Вы не хотите пробовать это с помощью обратных кавычек.
источник
$()
вами всегда создайте новый контекст цитирования", так что это как вне внешних кавычек. Насколько мне известно, больше ничего нет.Вы всегда можете показать эффект цитирования переменной с помощью
printf
.Разделение слов сделано на
var1
:var1
цитируется, так что без словРазделение слов
var1
внутри$()
, эквивалентноecho "hello" "world"
:Нет слов для разделения
var1
, нет проблем с не цитированием$()
:var1
Снова разделение слов :Цитируя оба, самый простой способ быть уверенным.
Глобинговая проблема
Отсутствие кавычки в переменной также может привести к глобальному расширению ее содержимого:
Обратите внимание, что это происходит только после раскрытия переменной. Нет необходимости указывать глобус во время присваивания:
Используйте,
set -f
чтобы отключить это поведение:И
set +f
чтобы снова включить его:источник
var1='hello * world'
чтобы проиллюстрировать проблему глобализации.Дополнение к принятому ответу:
Хотя я в целом согласен с ответом @ l0b0 здесь, я подозреваю, что размещение оголенных знаков в списке «от худшего к лучшему» является, по крайней мере, частично результатом предположения,
$(...)
которое доступно везде. Я понимаю, что вопрос касается Bash, но есть много случаев, когда Bash имеет в виду/bin/sh
, что не всегда может быть полной оболочкой Bourne Again.В частности, простая оболочка Bourne не будет знать, что делать с ней
$(...)
, поэтому сценарии, которые утверждают, что совместимы с ней (например, через#!/bin/sh
строку shebang), вероятно, будут вести себя неправильно, если они на самом деле управляются «реальными»/bin/sh
- это особый интерес, когда, скажем, создание сценариев инициализации или упаковка предварительных и постскриптовых сценариев и может привести к их неожиданному расположению во время установки базовой системы.Если что-то из этого звучит как то, что вы планируете делать с этой переменной, вложение, вероятно, не так важно, как на самом деле предсказуемо запустить скрипт. Когда дело обстоит достаточно просто, и переносимость вызывает беспокойство, даже если я ожидаю, что скрипт обычно запускается в системах, где
/bin/sh
установлен Bash, по этой причине я часто склоняюсь к использованию обратных галочек с несколькими назначениями вместо вложенности.Сказав все это, повсеместное распространение оболочек, которые реализуют
$(...)
(Bash, Dash и др.), Оставляет нам хорошее место для того, чтобы придерживаться более красивого, удобного для размещения и более позднего предпочтительного синтаксиса POSIX в большинстве случаев, для все причины, о которых упоминает @ l0b0.В сторону: это иногда появлялось и в StackOverflow -
источник