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

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

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

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

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

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

  • Как использовать переменные в команде sed
  • Подстановка переменных grep и командной строки
  • Как я могу поддерживать разрывы строк в тексте тела с mailx при отправке вложений?
  • bash: невозможно установить переменную в сплошную строку
  • Как процитировать строку, содержащую знак доллара $ и одинарную цитату '?
  • Многострочная переменная с пробелами, добавление каждой строки в массив
  • Почему исходный текст не работает, когда я вызываю bash -c
  • Как назначить имена файлов пробелу другой переменной без потери разделителя
  • 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. 
    Linux и Unix - лучшая ОС в мире.