В чем разница, имеющая двойные кавычки или нет в bash

У меня есть несколько сценариев bash, один из которых имеет следующий контент:

#!/bin/bash source $(dirname ${BASH_SOURCE[0]})/script.sh 

в то время как другой имеет следующее содержание:

 #!/bin/bash source "$(dirname ${BASH_SOURCE[0]})/script.sh" 

Как эти сценарии ведут себя по-разному и почему? В чем разница?

3 Solutions collect form web for “В чем разница, имеющая двойные кавычки или нет в bash”

Основное различие заключается в том, что цитируемая версия не подвержена разбиению поля оболочкой.

С двойными кавычками результат расширения команды будет подаваться как один параметр в команду source . Без кавычек он будет разбит на несколько параметров, в зависимости от значения IFS которое по умолчанию содержит пространство, TAB и новую строку.

Если имя каталога не содержит таких пробелов, то разбиение поля не происходит.

Как правило, лучше использовать двойные кавычки с подстановками команд и расширениями переменных.

Без кавычек строка подвержена разбиению и глобализации слов . См. Также BashPitfalls # 14 .

сравнить

 $ echo $(printf 'foo\nbar\nquux\n*') foo bar quux ssh-13yzvBMwVYgn ssh-3JIxkphQ07Ei ssh-6YC5dbnk1wOc 

с

 $ echo "$(printf 'foo\nbar\nquux\n*')" foo bar quux * 

Когда происходит разбиение слов, первый символ IFS действует как разделитель (который по умолчанию является пространством).

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

  • В выражениях, где слово splitting / globbing не происходит, например, простые (не-массивные) назначения и оператор case . Все безопасны:

    • foo=*
    • foo=${bar}qux${quux}
    • foo=$(bar "${quux}")
    • case ${var} in

    Это, однако, не (если то, что вам нужно, – это один элемент с буквальным символом звездочки):

    • foo=( * )
  • Когда вы специально хотите разделить слово, например, перебирать токены в строке с разделителями пробелов (с отключенным отключением). Однако, если возможно, используйте массив.

Вероятнее всего, самым важным отличием будет то, что каталог, в котором находится скрипт, имеет место в нем. В этом случае первая строка, без двойных кавычек, потерпит неудачу. Это было бы результатом «расщепления слов», которое bash делает для некотируемых строк.

Предположим, что результатом dirname ${BASH_SOURCE[0]} является /home/jr/bin . Рассмотрим строку без кавычек:

 source $(dirname ${BASH_SOURCE[0]})/script.sh 

В этом случае bash увидит команду:

 source /home/jr/bin/script.sh 

После разделения слов source команда видит имя скрипта /home/j и аргумент скрипту r/bin/script.sh . Скорее всего, скрипта нет, и bash вернет сообщение об ошибке:

 bash: /bin/j: No such file or directory 

Теперь рассмотрим, что происходит с двойными кавычками:

 source "$(dirname ${BASH_SOURCE[0]})/script.sh" 

В этом случае команда source будет искать сценарий с именем /home/jr/bin/script.sh и попытаться его /home/jr/bin/script.sh .

Для полноты рассмотрим одинарные кавычки:

 source '$(dirname ${BASH_SOURCE[0]})/script.sh' 

В этом случае, в отличие от предыдущих двух, dirname никогда не выполняется. $(dirname ${BASH_SOURCE[0]})/script.sh команда попытается установить команду с литеральным именем $(dirname ${BASH_SOURCE[0]})/script.sh . Вероятно, нет такого файла, и bash выдаст сообщение об ошибке.

Как bash рассматривает строки в двойных кавычках, подробно описывается в man bash :

  Enclosing characters in double quotes preserves the literal value of all characters within the quotes, with the exception of $, `, \, and, when history expansion is enabled, !. The characters $ and ` retain their special meaning within double quotes. The backslash retains its special meaning only when followed by one of the following characters: $, `, ", \, or <newline>. A double quote may be quoted within double quotes by preceding it with a backslash. If enabled, history expansion will be performed unless an ! appearing in double quotes is escaped using a backslash. The backslash preceding the ! is not removed. 
  • Почему \ n расширяется до n в bash?
  • cp не работает в скрипте, но работает в терминале
  • Как скобки интерпретируются в командной строке?
  • Цитирование и побег
  • Есть ли причина, чтобы указать статус выхода $? переменная?
  • Почему команда grep игнорирует период в строке поиска?
  • Передача аргументов с кавычками и двойными значениями в сценарий bash
  • Как процитировать строку, содержащую знак доллара $ и одинарную цитату '?
  • Bash - почему я могу выполнять командную строку с конвейерами только через «bash -c»?
  • Сценарий Bash не конвертирует переменные
  • Проблема использования пользовательской переменной в скрипте
  • Сценарии - Папки с пробелами
  • Linux и Unix - лучшая ОС в мире.