Кавычки
Кавычки, обрамляющие строку, предотвращают интерпретацию специальных символов, которые могут находиться в строке. Символ называется "специальным", если он не только означает самого себя но и имеет дополнительное значение для программ, например символ шаблона -- *.
В этом примере, символ "*", интерпретируется как шаблон:
freebsd82 /work-tests/sh# ll [Bb]* # ll - в данном случае псевдоним для команды ls -lASo -rw-r--r-- 1 root wheel - 0 Apr 27 12:44 BOOBOO.TXT -rw-r--r-- 1 root wheel - 0 Apr 27 12:44 booboo.txt -rw-r--r-- 1 root wheel - 0 Apr 27 12:45 brrr
А тут просто как символ "звездочка", естественно команда ls, не находит такого файла:
freebsd82 /work-tests/sh# ll '[Bb]*' # одинарные кавычки ls: [Bb]*: No such file or directory freebsd82 /work-tests/sh# ll "[Bb]*" # двойные кавычки ls: [Bb]*: No such file or directory
Имейте в виду, многие программы в передаваемых им параметрах, используют специальные символы, в этом случае нужно заключать их в кавычки, что-бы системная оболочка их не трогала, оставляя для вызываемой программы.
В примере ниже, производится поиск в файлах, начинающихся на символы B или b в текущем рабочем каталоге, строк, начинающихся с символов T или t. Команда grep, получает в качестве параметра шаблон, если не заключить его в кавычки, он будет интерпретирован оболочкой, до того как попадет к grep, и ничего найдено не будет:
freebsd82 /work-tests/sh# grep '[Tt]*' ./[Bb]* ./BOOBOO.TXT:Test line first ./BOOBOO.TXT:test line second ./booboo.txt:test line too ./brrr:mmm.. test it
При обращении к переменным, желательно использовать двойные кавычки. Это позволит не интерпретировать специальные символы, содержащиеся в именах переменных, за исключением символов $, ` ( обратная кавычка) и \ ( обратный слэш ). То что символ $ является исключением, позволяет производить подстановку переменных в строке , то есть сценарий:
#!/usr/local/bin/bash
var="variable"
echo "This is $var"
выведет:
freebsd82 /# ./test.sh This is variable
Кроме вышесказанного, двойные кавычки используются для предотвращения разбиения строки на слова:
#!/usr/local/bin/bash
var="is a variable"
echo this $var # здесь команде передается 4 аргумента
echo "this $var" # а тут один
Результат обеих команд echo, будет одинаков, но только на первый взгляд:
freebsd82 /work-tests/sh# ./test.sh this is a variable # здесь на выходе мы получаем 4 слова this is a variable # а здесь одну строку
Заключать в кавычки аргументы команды echo, нужно только если разбиение вывода на слова, вызывает какие-то трудности.
Пример вывода необычных переменных:
#!/usr/local/bin/bash
var="'(]\\{}\$\""
echo $var
echo "$var"
echo
IFS='\' # Меняем разделитель полей
echo $var
echo "$var"
freebsd82 /work-tests/sh# ./test.sh '(]\{}$" '(]\{}$" '(] {}$" # символ \ заменен пробелом '(]\{}$"
Одиночные кавычки (' '), по своему действию схожи с двойными кавычками, но не разрешают внутри себя подстановку переменных, интерпретируя символ "$", как обычный символ. Любой символ внутри одинарных кавычек, за исключением символа одинарной кавычки, воспринимается как обычный символ.
Одинарные кавычки являются более строгим вариантом двойных кавычек.
Поскольку внутри одиночных кавычек даже экранирующий (\) символ воспринимается как обычный символ, попытка вывести одиночную кавычку внутри строки, ограниченной одинарными кавычками, не даст желаемого результата, хотя при желании это можно обойти.
#!/usr/local/bin/bash
echo 'Why can't I write 's between single quotes'
echo 'Why can'\''t I write '"'"'s between single quotes'
Вторая строка разбита на 3 подстроки, ограниченных одинарными кавычками, а между подстроками стоят экранированные одинарные кавычки, в первом случае кавычка экранируется с помощью обратного слэша, во втором, с помощью двойных кавычек.
freebsd82 /work-tests/sh# ./test.sh Why cant I write s between single quotes Why can't I write 's between single quotes
При использовании с некоторыми командами, например echo и sed, экранирующий символ может применяться для получения инверсного результата, когда обычные символы при экранировании приобретают специальное значение.
Специальное назначение экранированных символов в echo и sed
- \n
- Символ перевода строки (новая строка)
- \r
- Символ перевода каретки
- \t
- горизонтальная табуляция
- \v
- вертикальная табуляция
- \b
- забой (backspace)
- \a
- "звонок" (сигнал)
- \0xx
- ASCII-символ с кодом 0xx в восьмеричном виде)
- \"
- кавычки
echo "He said: \"Hi\"." # Будет выведено He said: "Hi". - \$
- символ доллара. Если за конструкцией \$ идет переменная, подстановка значения этой переменной, выполнена не будет.
echo "\$var" # будет выведено $var - \\
- обратный слэш
echo "\\" # выведет \
Поведение символа "\" ( обратный слэш ), зависит от разных факторов, таких как: экранирован-ли он, заключен-ли в кавычки, используется в подстановке команд или в конструкции "вложенный документ".
# Простое экранирование и кавычки
# возвращаемое значение
echo \z # z
echo \\z # \z
echo '\z' # \z
echo '\\z' # \\z
echo "\z" # \z
echo "\\z" # \z
# Подстановка команды
echo `echo \z` # z
echo `echo \\z` # z
echo `echo \\\z` # \z
echo `echo \\\\z` # \z
echo `echo \\\\\\z` # \z
echo `echo \\\\\\\z` # \\z
echo `echo "\z"` # \z
echo `echo "\\z"` # \z
# Встроенный документ
cat <<EOF
\z
EOF # \z
cat <<EOF
\\z
EOF # \z
Отдельные символы в строке, которая записывается в переменную, могут быть экранированы, исключение составляет сам экранирующий символ.
#!/usr/local/bin/bash
var=\
echo "$var"
Данный сценарий вернет сообщение об ошибке:
freebsd82 /sh# ./esc.sh ./esc: line 4: : command not found
Фактически, в данном примере, экранируется символ перевода строки, в итоге команда получается такой var=echo "$var".
var=\
test
echo "$var" # выведет test, поскольку вторая строка ничего не нарушает с точки зрения присвоения значений переменным
var=\ # после \ ставим пробел
echo "$var" # вернет пробел
var=\\
echo "$var" # выведет \
var=\\\ # первый слэш экранирует второй, третий остается бесхозным
echo "$var" # выведет сообщение об ошибке
var=\\\\ # первый слэш экранирует второй, третий экранирует четвертый
echo "$var" # будет выведено \\
Экранирование пробелов в командной строке объединяет все аргументы в один, например команда:
freebsd82 /# ls /etc /root
вернет листинг каталогов /etc и /root, а вариант
freebsd82 /# ls /etc\ /root
вернет "No such file or directory", поскольку фактически мы сказали команде ls вывести листинг каталога /etc/root, которого не существует.
Очень часто символ экранирования \ ( обратный слэш ), используется для ввода из командной строки многострочных команд, экранируя символ новой строки:
freebsd82 /sh# ( cd ./dir1 && tar cf - .) | \ ? ( cd ./dir2 && tar xpvf - ) x ./ x ./BOOBOO.TXT x ./booboo.txt x ./brrr
Приведенная команда копирует содержимое одной директории в другую, записана в 2 строки.
Другой вариант той-же операции:
freebsd82 /# tar cf - -C ./dir1 . |\ ? tar xpvf - -C ./dir2 x ./ x ./BOOBOO.TXT x ./booboo.txt x ./brrr
Вообще если одна из строк многострочной команды заканчивается символом конвейера " | ", экранировать символ новой строки не обязательно, это просто считается хорошим тоном, и применимо только к оболочке bash, например в csh это не работает.
echo "foo
bar"
Выведет:
#foo
#bar
echo 'foo
bar'
С строгими кавычками, результат будет тот-же
echo foo\
bar
Перевод строки экранирован, поэтому вывод будет:
#foobar
echo "foo\
bar"
Внутри не строгих кавычек слэш работает как экранирующий, вывод будет:
#foobar
echo 'foo\
bar'
В одинарных ( строгих ) кавычках, слэш интерпретируется как обычный символ и ничего не экранирует, вывод будет:
#foo\
#bar