Успение с двойными кавычками, одинарные кавычки и без кавычек
В 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]
-
Мне очень понравились данные Hauri $'...' и $"..." - однако это не то, о чем мы говорим. Они действительно ведут себя, как говорится в справочной странице bash. $'' отличается от '' так как (()) от $(())
-
Я был в восторге от этого, так что...
$ 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, касающийся одиночных и двойных кавычек: (это почти тот же контент, что и справочное руководство)
Вложения символов в одинарных кавычках сохраняют буквальное значение каждый символ в кавычках. Одиночная цитата может не произойти между одинарными кавычками, даже когда предшествует обратная косая черта.
Вложения символов в двойные кавычки сохраняют буквальное значение все символы внутри кавычек, за исключением $, `,\и, когда включено расширение истории!! Символы $и ` сохраняют свое особое значение в двойных кавычках. Обратная косая черта сохраняет свое особое значение только тогда, когда следует одно из следующих символы: $, `,", \, или. Двойная кавычка может быть цитируется в двойных кавычках, предшествуя ему обратным слэшем. Если включенное, расширение истории будет выполнено, если только! появляется в двойных кавычках, с помощью обратной косой черты. обратная косая черта, предшествующая! не удаляется.