Почему делает расширение параметра с пробелами без работы кавычек в двойных скобках “[[”, но не в одиночных скобках “[”?

Существует действительно простой способ сделать это использование awful дополнительный пакет. Некоторые дистрибутивы связывают это автоматически, у других есть он как подпакет. После того как у Вас есть он, можно просто использовать встроенный awful.client.movetoscreen. Например, у меня есть привязка, которая похожа на это:

awful.key({modkey}, "o", awful.client.movetoscreen)

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

89
30.11.2017, 19:22
4 ответа

Одиночная скобка [ на самом деле псевдоним для test команда, это не синтаксис.

Одна из оборотных сторон (многих) одиночной скобки - то, что, если один или несколько операндов она пытается оценить, возвращают пустую строку, она будет жаловаться, что ожидала два операнда (двоичный файл). Поэтому Вы видите, что люди делают [ x$foo = x$blah ], x гарантии, что операнд никогда не будет оценивать к пустой строке.

Двойная скобка [[ ]], с другой стороны, синтаксис и намного более способен, чем [ ]. Как Вы узнали, это не имеет единственной проблемы операнда, и это также допускает более подобный синтаксису C с >, <, >=, <=, !=, ==, &&, || операторы.

Моя рекомендация следующая: Если Ваш интерпретатор #!/bin/bash, затем всегда используйте [[ ]]

Важно отметить это [[ ]] не поддерживается всеми оболочками POSIX, однако много оболочек действительно поддерживают его такой как zsh и ksh в дополнение к bash

86
27.01.2020, 19:30
  • 1
    Пустая строка (и многие другой) проблема решена при помощи кавычек. "x" должен покрыть другой вид проблем: где операнды могут быть взяты в качестве операторов. Как когда $foo ! или ( или -n... Та проблема не предназначена, чтобы быть проблемой с оболочками POSIX где количество аргументов (около [ и ]) не больше, чем четыре. –  Stéphane Chazelas 25.01.2013, 22:36
  • 2
    Разъясниться, [ x$foo = x$blah ] так же, как плоскость неправильно как [ $foo = $bar ]. [ "$foo" = "$bar" ] корректно в любом POSIX совместимая оболочка, [ "x$foo" = "x$bar" ] работал бы в любой подобной Границе оболочке, но x не для случаев, где у Вас есть пустые строки, но где $foo может быть ! или -n... –  Stéphane Chazelas 07.03.2013, 18:29
  • 3
    Интересная семантика в этом ответе. Я не уверен, под чем Вы подразумеваете, это *не* синтаксис. Конечно, [ не точно псевдоним для test. Если это было, то test принял бы заключительную квадратную скобку. test -n foo ]. Но test не делает, и [ требует того. [ идентично test во всех других отношениях, но это не то, как alias работы. Bash описывает [ и test как окружают builtins, но [[ как ключевое слово оболочки. –  kojiro 09.10.2017, 16:02

[ команда является обычной командой. Хотя большинство оболочек обеспечивает его как встроенное для эффективности, это соблюдает нормальные синтаксические правила оболочки. [ точно эквивалентно test, за исключением того, что [ требует a ] как его последний аргумент и test не делает.

Двойные скобки [[ … ]] специальный синтаксис. Они были представлены в ksh (спустя несколько лет после этого [) потому что [ может быть неприятным для использования правильно и [[ позволяет некоторым новым хорошим дополнениям ту оболочку использования специальные символы. Например, можно записать

[[ $x = foo && $y = bar ]]

потому что все условное выражение анализируется оболочкой, тогда как [ $x = foo && $y = bar ] был бы сначала разделен на две команды [ $x = foo и $y = bar ] разделенный && оператор. Столь же двойные скобки включают вещи как синтаксис сопоставления с образцом, например. [[ $x == a* ]] протестировать ли значение x запускается с a; в одиночных скобках это расширилось бы a* к списку файлов, имена которых запускаются с a в текущем каталоге. Двойные скобки были сначала представлены в ksh и только доступны в ksh, ударе и zsh.

В одиночных скобках необходимо использовать двойные кавычки вокруг подстановок переменных, как в большинстве других мест, потому что они - просто аргументы команде (который, оказывается, [ команда). В удваивают скобки, Вам не нужны двойные кавычки, потому что оболочка не делает разделения слова или globbing: это анализирует условное выражение, не команду.

Исключение, хотя [[ $var1 = "$var2" ]] где Вам нужны кавычки, если Вы хотите сделать сравнение байта к строке байтов, иначе, $var2 был бы шаблон для соответствия $var1 против.

Одна вещь Вы не можете сделать с [[ … ]] использование переменная как оператор. Например, это совершенно законно (но редко полезно):

if [ -n "$reverse_sort" ]; then op=-gt; else op=-lt; fi
…
if [ "$x" "$op" "$y" ]; then …

В Вашем примере

dir="/home/mazimi/VirtualBox VMs"
if [ -d ${dir} ]; then …

команда в if [ с этими 4 аргументами -d, /home/mazimi/VirtualBox, VMs и ]. Синтаксические анализы оболочки -d /home/mazimi/VirtualBox и затем не знает, что сделать с VMs. Необходимо было бы предотвратить разделение слова на ${dir} получить правильно построенную команду.

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

  • в присвоении: foo=$bar (но обратите внимание необходимость в двойных кавычках в export "foo=$bar" или в присваивании массива как array=("$a" "$b"));
  • в a case оператор: case $foo in …;
  • в удваивают скобки за исключением правой стороны = или == оператор (если Вы действительно не хотите сопоставления с образцом): [[ $x = "$y" ]].

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

53
27.01.2020, 19:30

Для обработки пробелов и blank|special символов в переменных необходимо всегда окружать их двойными кавычками. Установка надлежащей IFS является хорошей практикой также.

Рекомендуется: http://www.dwheeler.com/essays/filenames-in-shell.html

2
27.01.2020, 19:30

Когда следует заключать в двойные кавычки такие переменные, как "$ {var}" , чтобы предотвратить проблемы, вызванные пробелами?

В этом вопросе подразумевается

Почему $ { имя_переменной } недостаточно хорошо?

$ { имя_переменной } не t означает то, что вы думаете, что он делает…

… если вы думаете, что у него есть что-нибудь , чтобы решить проблемы, вызванные пробелами (в значениях переменных). $ { имя_переменной } подходит для этого:

$ bar=foo
$ bard=Shakespeare
$ echo $bard
Shakespeare
$ echo ${bar}d
food

и ничего больше! 1 $ { имя_переменной } не принесет никакой пользы , если вы не сразу после него следует символ , который может быть частью имени переменной: буква ( A - Z или a - z ), подчеркивание ( _ ) или цифра ( 0 - 9 ). И даже тогда вы можете обойти это:

$ echo "$bar"d
food

Я не пытаюсь препятствовать его использованию - echo "$ {bar} d" , вероятно, лучшее решение здесь - , но чтобы отговорить людей полагаться на фигурные скобки вместо кавычек, или инстинктивно применять фигурные скобки, а затем спрашивать: «А теперь, могу ли я нужны цитаты, тоже? » Вы всегда должны использовать кавычки, если у вас нет веской причины не делать этого, и вы уверены, что знаете, что вы делает.
_________________
1 За исключением, конечно, того факта, что более интересная форма расширения параметра , например, $ { параметр : - [ слово ]} и параметр $ { % [ слово ]} , основан на синтаксисе $ { параметра } . Кроме того, вам необходимо использовать $ {10} , $ {11} и т. Д., для ссылки на 10-е, 11-е и т. Д. , позиционные параметры - кавычки в этом вам не помогут.

9
20.08.2021, 13:28

Теги

Похожие вопросы