Перед запуском введенной команды интерпретатор анализирует ее на наличие так называемых метасимволов, т. е. символов, имеющих специальное значение.
Так, например, пробел отделяет аргументы команды друг от друга, шаблонные выражения на основе ?, *, и [] вычисляются в имена файлов, доллар $ активирует подстановку команд, параметров или арифметических выражений, а символы <, >, | — перенаправления потоков.
В определенных командах требуется использовать литеральное (буквальное) значение метасимволов, как, например, в листинге ниже для манипулирования файлами, в именах которых содержатся пробелы. Для отмены специального значения метасимволов используется их экранирование при помощи конструкций \m, ‘m1m2m3….mn‘ или «m1m2m3….mn« «отменяющих» метасимволы m, m1, …,mn.
Содержимое
Экранирование пробельных символов
bender@ubuntu:/usr/share/onboard/themes$ ls -l
итого 88
-rw-r—r— 1 root root 2637 февр. 16 2012 Classic Onboard.colors
-rw-r—r— 1 root root 436 февр. 16 2012 Classic Onboard.there
bender@ubuntu:/usr/share/onboard/theres$ file Classic Onboard.colors
Classic: ERROR: cannot open ‘Classic’ (No such file or directory)
Onboard.colors: ERROR: cannot open ‘ Onboard.colors’ (No such file or directory)
bender@ubuntu:/usr/share/onboard/theres$ file Classic\ Onboard.colors
Classic Onboard.colors: XML document text
bender@ubuntu:/usr/share/onboard/thenes$ file «Classic Onboard.colors”
Classic Onboard.colors: XML document text
bender@ubuntu:/usr/share/onboard/theres$ file ‘Classic Onboard.colors’
Classic Onboard.colors: XML document text
В примере из листинга выше показано экранирование символа пробела в имени файла, который привел к разбиению имени файла на два аргумента команды file, ни один из которых естественно не является именем какого-либо файла. В примере используется одиночное экранирование пробела при помощи \m, а далее — множественное экранирование всех символов в кавычках » и включая пробел.
В менее тривиальных случаях, как в примере из листинга ниже, попытка выполнения команды find с вполне валидными аргументами приводит к неожиданным и странным результатам.
В режиме трассировки команд интерпретатора становится очевидно, что шаблонное выражение *.gz, предназначавшееся самой команде поиска файлов, было подставлено интерпретатором до запуска команды, что привело ее в недоумение.
Для правильной передачи шаблонных выражений самим командам их следует экранировать.
Экранирование шаблонных выражений
bender@ubuntu:~$ find . -name *.gz
find: все пути должны предшествовать выражению: plan9.iso.gz
Использование: find [-Н] [-L] [-Р] [-Оуровень] [-D help|tree|search|stat|rates|opt|exec]
[путь…] [выражение]
bender@ubuntu:~$ set -x
bender@ubuntu:~$ find . -name *.gz
+ find . -name dvd.iso.gz plan9.i5o.gz
find: все пути должны предшествовать выражению: plan9.iso.gz
Использование: find [-H] [-L] [-P] [-Оуровень] [-D help|tree|search|stat|rates|opt|ехес]
[путь…] [выражение]
bender@ubuntu:~$ find . -name «*.gz «
+ find . -name ‘*.gz’
./dvd.iso.gz
./plan9.iso.gz
Аналогично, в примере из листинганиже при попытке скачивания с Web-сервера ресурса со сложным W:[URL] при помощи команды wget командный интерпретатор постарался разбить команду на список заданий, встретив метасимвол &, формирующий асинхронные задания.
Для правильной передачи строк, содержащих метасимволы, их следует экранировать, как в примере.
Экранирование символов списка команд &
bender@ubuntu:~$ wget https: //r4- — -sn-xjpm-4g5e. googlevideo. com/videoplayback?signature=D017 06B19078430C4AB2E7E0E8A1C03A685Q48F5.53412B263BA6F90E9DBlADD7F175E6AB4F7F18A3&expire=14511669 72&pl=24&nv=u&nt=1451145210&nis=au&id=o-ANXmoZGwlgBo02QKDOnA9iQcFzRyI8UhFWlgl5Wll8c&nn=sn-xjp n-4g5eSm=31&key=yt6&ipbits=0&rnne=video%2Fnp4&source=ycHitube&sver=3&du r=5104.2108itag=188fex p=9407536%2C9412913%2C9413141%2C9416126%2C9416984%2C9417206%2C9418203%2C9418777%2C9420452%2C9 420540%2C9421665%2C9422596%2C9423662%2C9424114%2C9424629%2C9424845%2C9425448%2C9425953%2C9426 410%2C9426494&ratebypass=yes&lnt=1394506818301594&ip=185.53.168.70&requiressl=yes&sparans=dur %2Cid%2Cip%2Cipbits%2Citag%2ClntVOTlne%2Crri%2Crin%2Qns%2Cnv%2Cpl%2Cratebypass%2Crequiress’lX2C sou rce%2Cupn%2Cexpire&upn=tkA065sWc j 8&title=%OO%A4%DO%B8%DO%BB%Dl%8C%DO%BOo20%DO%8E%20GNU/Lin ux%20Revolutlon%20OS%2O[RU] -0 revolution-os.mp4
[1] 5215
—2018-12-26 19:00:05— https://r4—sn-xjpm-
4g5e. googlevideo. com/videoplayback?signature=D01706B19078430C4AB2E7E0E8AlC03A685048F5.53412B2 638A6F90E9OB1ADD7F175E6AB4F7F18A3
[23] 5237
[2] Готово expire=1451166972
Распознаётся r4—sn-xjpm-4g5e.googlevideo.com .(r4—sn-xjpm-‘%j5e.googlevideo.com)…
Подключение к r4—sn-xjpn-4g5e.googlevideo.com (r4—sn-xjpm-4g5e.googlevideo. com) 1194.122.81.151:443… соединение установлено.
HTTP-запрос отправлен. Ожидание ответа… 403 Forbidden
2018-12-26 19:00:05 ОШИБКА 403: Forbidden.
bender@ubuntu:~$ wget ‘https://r4—sn-xjppi-4g5e.googlevideo.com/videoplayback7signaturesOQi 706B19078430C4AB2E7E0E8A1C03A685O48F5.53412B263BA6F90E9DBlADO7F175E6AB4F7F18A3&explre=1451l66 972&pl=24env=u&nt=1451145210&ns=au&id=o-ANXnoZQwigBoC32QKD0nA9iQcFzRyI8UhFWlgl5Nll8c8nn=sn-xj
pn-4g5e&m=31&key=yt6&ipbits=0&nine=video%2Fnp4&sourcG=youtube&sver=3&dur=5104.210&itag=l8&fe
хр=94О7536%2С9412913%2С9413141Уо2С941612б%2С9416984%2С94172Об%2С9418203%2С9418777%2С942О452%2С 942054O%2C9421665%2C9422596%2C9423662%2C9424114%2C9424629%2C9424845%2C9425448%2C9425953%2C942 6410%2C9426494&ratebypass=yes&lnt=1394506818301594&ip=185.53.168.70&requiressl=yes&sparans=du r%2Cid%2Cip%2Cipbits%2Citag%2Clnt5i2Cnine%2Cpn%2Cnn%2Cns%2Cnv%2Cpl%2Cratebypass%2Crequiresslyo2 Csource%2Cupn%2Cexpire&upn=tkAO65sWcj8&title=%D0%A4%DO%B8%O0%BB%01%8C%DO%BC%2O%D0%BE%20GNU/Li nux%20Revolution%20OS9620[RU] -0 linux-revolution-os.mp4’ -0 revolution-os.mp4
Распознаётся r4—sn-n8v7zn76.googlevideo.com (…)… 74.125.13.211, 2a00:1450:4011:1a::13
Подключение к r4—sn-n8v7zn76.googlevideo.com (…)|74.125.13.211|:443… соединение установлено.
HTTP-запрос отправлен. Ожидание ответа… 200 OK
Длина: 260800224 (249М)
Сохранение в: «revolution-os.mр4»
100%[==================================================== —>]
260 800 224 2,85M/s за 86s
2018-12-26 19:19:23 (2,91 MB/s) — «revolution-os.mp4» сохранён [260800224/260800224]
В листингах ниже использованы разные способы множественного экранирования » и ‘ ‘ хотя в этих примерах между ними нет разницы.
Экранирование метасимволов в двойных кавычках » « носит название слабого экранирования, потому что не распространяется на метасимволы подстановки $ и ´ ´и метасимвол одиночного экранирования \.
Экранирование метасимволов в одинарных кавычках « носит название сильного экранирования, потому как распространяется на абсолютно любые метасимволы.
Сильное и слабое экранирование
bender@ubuntu:~$ cal
Декабрь 2018
Вс Пн Вт Ср Чт Пт Сб
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31
bender@ubuntu:~$ notify-send $(date) $(cal)
Invalid number of options.
bender@ubuntu:~$ set -x
bender@ubuntu:~$ notify-send $(date) $(cal)
++ date
++ cal
+ notify-send $’\320\241\320\261.’ $’\32©\264\320\26S\320\272.’ 26 20:21:59 MSK 2015 $k\320\224\320\265\320\272\320\260\320\261\321\200\321\214′ 2015 $’ \320\222\321\201′
$P\320\237\320\2751 $ ’ \320\222\321\202 ’ $’ \320\241\321\200′ $’ \320\247\321\202′ $’\320\237\321\202′ $’\320\241\320\2611 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 $’_\b2_\b6′ 27 28 29 30 31
bender@ubuntu:~$ notify-send ‘$(date)’ ’$(cal)’
+ notify-send ‘$(date)’ ‘$(cal)’
bender@jbuntu:-$ notify-send »$(date)» «$(cal)
++ date
++ cal
+ notify-send ‘Сб. дек. 26 20:28:28 MSK 2018’ ‘ Декабрь 2018
Вс Пн Вт Ср Чт Пт Сб
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31
В примерах из листинга выше необходимо текущее время и календарь на текущий месяц отправить пользователю в качестве уведомления в сеансе графического интерфейса.
При помощи команды notify-send можно послать уведомление, заголовок которого передается первым ее параметром, а текст уведомления— вторым.
Прямое решение с подстановками вывода команд date и cal не срабатывает и завершается со странным результатом. В режиме трассировки команд интерпретатора видно, что пробелы … в выводе команд date и cal были естественным образом подставлены как аргументы команды notify-send, что привело к передаче более чем двух ожидаемых аргументов.
Решение с сильным экранированием посылает уведомление с литеральным написанием подстановок, без их выполнения, что тоже не является ожидаемым результатом. Слабое экранирование работает, как ожидается,
С выполнением подстановок и экранированием пробелов после выполнения подстановки, в результате чего формируются два правильных аргумента команды notify-send.