Успение с двойными кавычками, одинарные кавычки и без кавычек

В bash:

Использование двойных кавычек

echo "*" #Globbing is never done
echo "$variable" # Variable expansion is always done
echo "$(command)" # command expansion is always done

Использование одинарных кавычек

echo '*' #Globbing is never done 
echo '$variable' # Variable expansion is never done
echo '$(command)' # command expansion is never done

Использование кавычек

echo * #Globbing always done.
echo $variable; # Variable expansion is always done
echo $(command) # command expansion is always done

это применимо ко всем командам?

Ответ 1

Похоже, вы ищете исключения, и я думаю, вы имеете в виду. Я собираюсь сделать предположение, что set -f/set -o noglob исключаются из этого случая?

Когда вы используете команду dd, globbing не будет выполняться, даже если не указано.

$ ls *.txt
blah.txt  file1.txt  file2.txt  file.txt  logfile.txt
$ dd if=*.txt of=glob.txt
dd: failed to open ‘*.txt’: No such file or directory

Ребутальные и ложные срабатывания

Вот несколько примеров, которые являются нечетными, но следуйте расширению

variable='2010-09-08 12:34:56' echo "$variable" | xargs date +%s -d date: extra operand '12:34:56'

Дополнительный операнд показывает, что происходит расширение переменной, вы теряете кавычки в трубе. $ date +%s -d 2010-09-08 12:34:56 date: extra operand ‘12:34:56’

Это также происходит, если вы создаете script до echo $1, а затем расширяете свою цитированную переменную во время ее передачи. Он расширяется и работает так, как ожидалось. Итак, проблема связана не с xargs, а с расширением до нормального канала.

  • Eval... evals целая цель состоит в том, чтобы сделать расширение своих аргументов до запуска команды. Расширение также происходит с bash -c, за исключением того, что требуется один аргумент. Итак, опять же, это не проблема расширения, а проблема использования команд.

cmd='printf "%s\n" "$(date -d "$variable" +%c)"' bash -c $cmd

работает так же, как и расширенная версия

$ bash -c printf "%s\n" "$(date -d "$variable" +%c)" printf: usage: printf [-v var] format [arguments]

  1. Мне очень понравились данные Hauri $'...' и $"..." - однако это не то, о чем мы говорим. Они действительно ведут себя, как говорится в справочной странице bash. $'' отличается от '' так как (()) от $(())

  2. Я был в восторге от этого, так что... $ ls mclark.txt qt sign_in.txt skel.bash $ zip m*t.zip *t $ ls *.zip m*t.zip

Однако это тоже не так: splat расширяется, но без соответствия zip использует его как литерал. Я нашел несколько команд, которые сделали это, но если было совпадение (я добавил my.zip позже), он использует сопоставленное расширение (ошибка была выбрана, b/c my.zip был текстовым файлом для целей тестирования).

Ответ 2

Существует множество сил. В общем случае вы можете предположить, что одинарные кавычки должны скрывать содержимое от расширения bash. Двойные кавычки состоят в группировке значений, которые могут иметь пробел, чтобы bash рассматривал их как одну логическую единицу, но также отключил подталкивание. Есть много предостережений, хотя...

Вложения символов в двойные кавычки сохраняют буквальное значение все символы в кавычках, за исключением $, ',\и, когда включено расширение истории!! Символы $и 'сохранить их особое значение в двойных кавычках. Обратная косая черта сохраняется его особое значение, только если за ним следует одно из следующих символы: $, ', ",\или. Двойная кавычка может быть процитирована в двойных кавычках, предшествуя ему обратным слэшем. Если включено, расширение истории будет выполнено, если только! появляющийся в двойном кавычки экранируются с помощью обратного слэша. Обратная косая черта преследует! не удаляется.

Смотрите раздел QUOTING из man bash

В приведенном ниже примере будет либо запутываться, либо сделать это более ясным.

$ echo "*test*"
*test*

$ echo '*test*'
*test*

$ msg=$(echo '*test*')
$ echo '$msg'
$msg

$ echo "$msg"
*test*

$ echo $msg
speedtest test1 test2 test3 test4 test5 testdir

обратите внимание, что если совпадений не было, будет напечатано *test* не пустая строка, прокомментированная Хастуром.

некоторые другие интересные лакомые кусочки

Обратите внимание, что это не работает

$ echo 'single quotes don\'t escape'

но это работает

$ echo "\"double quotes\" escape"

но вы можете использовать один в другом, не выходя из

$ echo '"' "'"

Ответ 3

Если ничего не соответствует *.xtx, а файл a.txt - это файл  mv a.txt *.xtx также даст вам неожиданный результат. То же самое относится и к другим вещам, таким как cp, и даже это относится к нему как к какому-либо адресу:

$ ls *.xtx
/bin/ls: cannot access *.xtx: No such file or directory
$ echo "A" > *.xtx
$ ls *.xtx
*.xtx
$

В то время как все они должны возвращать ошибку, как если бы было больше одного файла, вы получили бы "двусмысленный переадресацию".

Ответ 4

Короткий ответ: Да

Это предположение в основном истинно, всегда!

variable='2010-09-08 12:34:56' 
vname=variable
date -d "$variable" +%s
1283942096

date -d "${!vname}" +%s
1283942096

date -d $variable +%s
date: extra operand '+%s'
Try 'date --help' for more information.

date -d '$variable' +%s
date: invalid date '$variable'

date -d ${!vname} +%s
date: extra operand '+%s'
Try 'date --help' for more information.

Но

  • Некоторые команды, такие как xargs, точно работают с расширением и распределением параметров.

    echo "$variable" | xargs date +%s -d
    date: extra operand '12:34:56'
    Try 'date --help' for more information.
    

    Вы должны использовать -0 arg для xargs:

    echo "$variable" | xargs -0 date +%s -d
    1283942096
    
  • Встроенные команды могут использовать аргументы по-разному, особенно eval:

    cmd='printf "%s\n" $(date -d "$variable" +%c)'
    eval $cmd
    Wed
    Sep
    8
    12:34:56
    2010
    
    cmd='printf "%s\n" "$(date -d "$variable" +%c)"'
    eval "$cmd"
    Wed Sep  8 12:34:56 2010
    
    eval $cmd
    Wed Sep  8 12:34:56 2010
    
    bash -c "$cmd"
    Mon May 16 00:00:00 2016
    
    bash -c $cmd
    printf: usage: printf [-v var] format [arguments]
    
  • Синтаксис смешной вещи под bash не ограничивается "..", '..' и ${}

    • $'...' позволяет печатать специальные символы, но не расширять переменные:

      echo $'This\tis\ta string containing ${variable}'
      This    is  a string containing ${variable}
      
    • Backticks: для совместимости всегда поддерживаются backtick. Если вы не очень читаемы, вы можете увидеть это в некоторых сценариях:

      echo `date +%c -d "${!vname}"`
      Wed Sep 8 12:34:56 2010
      
    • Синтаксис $"..." может быть использован для локализации:

      export TEXTDOMAIN=bash
      export LANG=fr_CH.utf-8
      echo $"Running"
      En cours d'exécution
      

Ответ 5

это применимо ко всем командам?

Да.

Из справочных руководств Bash:

3.1.2.2 Отдельные кавычки

Вложения символов в одинарных кавычках (') сохраняют литерал значение каждого символа в кавычках. Одиночная цитата не может происходят между одинарными кавычками, даже если предшествует обратная косая черта.

и

3.1.2.3 Двойные кавычки

Вложения символов в двойные кавычки (") сохраняют литерал значение всех символов в кавычках, за исключением $, `, \, и, когда расширение истории включено,!. Персонажи $и `сохраняют свое особое значение в двойных кавычках (см. Расширения оболочки). Обратная косая черта сохраняет только свое особое значение за которым следует один из следующих символов: $, `, ", \, или новой строки. В двойных кавычках обратная косая черта, за которой следует одна этих символов удаляются. Обратные косые черты предшествующих символов без особого значения остаются неизмененными. Двойная кавычка может быть цитируется в двойных кавычках, предшествуя ему обратным слэшем. Если включено, расширение истории будет выполнено, если только! появляясь в двойных кавычках выполняется с помощью обратного слэша. Обратная косая черта, предшествующая! не удаляется.

Специальные параметры * и @имеют особое значение, когда в двойном (см. Расширение параметров оболочки).

Ответ 6

Возможно, справочные руководства оболочки и страницы man-оболочки содержат предполагаемое поведение... но результат может не всегда быть тем, что изначально предназначалось.

Чтение раздела "QUOTING" на страницах руководства также интересно. Это раздел из справочной страницы bash, касающийся одиночных и двойных кавычек: (это почти тот же контент, что и справочное руководство)

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

Вложения символов в двойные кавычки сохраняют буквальное значение все символы внутри кавычек, за исключением $, `,\и, когда включено расширение истории!! Символы $и ` сохраняют свое особое значение в двойных кавычках. Обратная косая черта сохраняет свое особое значение только тогда, когда следует одно из следующих символы: $, `,", \, или. Двойная кавычка может быть цитируется в двойных кавычках, предшествуя ему обратным слэшем. Если включенное, расширение истории будет выполнено, если только! появляется в двойных кавычках, с помощью обратной косой черты. обратная косая черта, предшествующая! не удаляется.