Почему мы дважды цитируем оценку знака доллара в Bash?

Я знаю, что одинарные кавычки не будут оценивать, что внутри, и двойные кавычки будут. Я часто вижу, как люди цитируют цитату оценки доллара. Вот некоторые примеры:

  • for i in "${indices[@]}"; do
  • if [ "${a}" == 0 ]; then
  • ffmpeg -framerate 2 -pattern_type glob -i "*.png" -pix_fmt yuv420p output.mp4

Что делать, если мы не будем делать двойное цитирование выражения знака доллара? AFAIK, цикл for все еще работает.

  • Как использовать переменные в команде sed
  • Как анализировать переменную env в цитируемой строке?
  • Как напечатать «$» в документе здесь
  • Какие символы должны быть экранированы в аргументах командной строки?
  • sed - не добавляет новую строку EOF и заменяет букву не определенной
  • Почему исходный текст не работает, когда я вызываю bash -c
  • почему grep '\ ;.' expand to grep '\' '\;.' \ '' 'при выполнении над ssh?
  • Проблема с экранированием параметризованных аргументов
  • 2 Solutions collect form web for “Почему мы дважды цитируем оценку знака доллара в Bash?”

    Ваши три примера не совсем одинаковы.

    В последних двух:

     if [ "${a}" == 0 ]; then ffmpeg -framerate 2 -pattern_type glob -i "*.png" -pix_fmt yuv420p output.mp4 

    Если $a не был указан, а его значение содержит символы $IFS (по умолчанию пробел, табуляция и новая строка) или подстановочные символы, это приведет к [ более трех аргументов (рядом с [ и ] ), в результате чего ошибка; аналогично, если значение $a было пустой строкой, это привело бы к тому, что [ получить слишком мало аргументов:

     $ (a=0; [ $a == 0 ] && echo OK) OK 

    (но только если $IFS настоящее время не содержит 0 )

     $ (a='foo bar'; [ $a == 0 ] && echo OK) bash: [: too many arguments 

    (со значением по умолчанию $IFS )

     $ (a=; [ $a == 0 ] && echo OK) bash: [: ==: unary operator expected 

    (даже с пустым $IFS или с zsh (который в противном случае не реализует этот неявный оператор split + glob при некорректном расширении))

     $ (a='*'; [ $a == 0 ] && echo OK) bash: [: too many arguments 

    (при запуске в каталоге, содержащем как минимум 2 не скрытых файла).

    При цитировании нет ошибок:

     $ (a='foo bar'; [ "$a" == 0 ] && echo OK) $ (a=; [ "$a" == 0 ] && echo OK) 

    Ваш первый пример отличается. Правила о расширении в двойных кавычках являются особыми при использовании массивов; если a обозначает массив, то:

    • $a – это первый элемент массива (строго говоря, это ${a[0]} даже если элемент в индексе 0 не определен);

    • ${a[*]} или ${a[@]} являются элементами массива, дополнительно разбиваются на $IFS (пробел, табуляция, новая строка по умолчанию);

    • "${a[@]}" – это элементы массива, а не разделенные на $IFS .

    Итак, ваш цикл for i in "${indices[@]}"; do ... for i in "${indices[@]}"; do ... фактически не работает одинаково, в зависимости от содержимого массива. Например:

     $ (declare -aa=(abc); printf '%s\n' $a) a $ (declare -aa=(abc); printf '%s\n' ${a[*]}) a b c $ (declare -aa=(a 'b c'); printf '%s\n' ${a[*]}) a b c $ (declare -aa=(a 'b c'); printf '%s\n' ${a[@]}) a b c $ (declare -aa=(a 'b c'); printf '%s\n' "${a[*]}") abc $ (declare -aa=(a 'b c'); printf '%s\n' "${a[@]}") a bc 

    Короче говоря, это делается, чтобы избежать расширений, созданных специальными символами, которые могут быть внутри переменной, например ! , Двойные кавычки также называются «слабым цитированием», поскольку некоторые из символов будут интерпретироваться (знак доллара, обратная косая черта и обратная косая черта). Одиночные кавычки являются «сильными цитатами», и ничто не будет интерпретироваться.

    Цитирование документации по bash :

    3.1.2.3 Двойные котировки

    Закрывающие символы в двойных кавычках ( " ) сохраняют буквальное значение всех символов в кавычках, за исключением $ , backquote , \ , и, когда расширение истории включено ! .. Когда оболочка находится в режиме POSIX (см. Bash POSIX Mode), в двойных кавычках не имеет особого значения, даже если расширение истории включено …

    Примеры слабых и сильных цитат:

    • echo "Your PATH is: $PATH" – напечатает Your PATH is:<variable_content>
    • echo 'Your PATH is: $PATH' – напечатает Your PATH is: $PATH

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

    Связанные вещи:

    • Последствия для безопасности, забывающие процитировать переменную в оболочках bash / POSIX
    • Wiki – Цитаты и побеги
    Interesting Posts

    Обобщение uniq

    Как Node.js / модуль кластера передает новые соединения из процесса master / parent, дочерних процессов?

    Преобразовать шрифт .bdf / .pcf в .psf (u) для использования в качестве consolefont?

    При использовании awk / pattern / {print "text"} / patern / {print ""} есть шаблон ELSE?

    bash find: получить каталог найденного файла

    Каковы различия между KILL, SUSPEND и TERMINATE процесса

    Как я могу получить информацию о удаленных каталогах, установленных через sshfs?

    Ctrl-z не работает в vi, запущенном с терминала Gnome

    возможно ли определить установленные пакеты на вторичном смонтированном диске?

    Как присоединиться к строкам с одиночными столбцами максимум до 4 столбцов в одной строке?

    Как включить поддержку мыши в терминале Emacs?

    Настройка FreeBSD Broadcom BCM43225

    xrandr rotate left right faild

    как ssh обнаруживает имена хостов в сети?

    Как использовать адрес содержимого в sed в osx без ошибки «ожидаемый контекстный адрес»

    Linux и Unix - лучшая ОС в мире.