Подстановки вывода команд и параметров являются для программирования на языке командного интерпретатора практически самыми важными конструкциями.
Например, используя операцию присвоения, подстановку вывода и внешнюю команду expr, предназначенную для вычисления арифметических выражений, можно вычислять значения одних переменных на основе других, как показано в примере из листинга ниже.
Нужно отметить, что аргументы команды еexpr отделяются пробелами, как и у любой другой команды, например ls.
Запуск внешних команд влечет за собой накладные расходы в виде системных вывозов fork и execve, поэтому во многих диалектах языка командного интерпретатора реализованы аналогичная встроенная команда арифметических вычислений let и арифметическая подстановка в виде стандартной POSIX-конструкции $((expression)), а в некоторых еще и в нестандартном виде $[expression].
Использование команды let в примере из листинга ниже, наоборот, исключает пробелы в арифметическом выражении, т. к. оно целиком является одним ее аргументом. В случае использования арифметической подстановки в примере пробельные символы могут быть применены произвольным образом.
Содержимое
Арифметические действия командного интерпретатора
bender@ubuntu: ~$ CIRCLE=’expr 2 * $RADIUS * 355 / 113′
bender@ubuntu:~$ let CIRCLE=2*RADIUS*355/113
bender@ubuntu:~$ CIRCLE=$((2 * RADIUS * 355/113))
Подстановки арифметических выражений полезно применять для пересчета значений в аргументах разных команд, использующих «неудобные» единицы измерения.
Так, например, в листинге ниже при поиске библиотек больше 10 Мбайт нужно задавать количество байтов (символов), которое и составит искомые десять килобайт килобайтов.
Библиотеки больше 10 Мбайт
bender@ubuntu:~$ set -x
bender@ubuntu:~$ find /lib /usr/lib -name ‘*.so.*’ -size +$((1024*1024*10))c
+ find /lib /usr/lib -name ‘*.so.*’ -size +10485760C
/usr/lib/libicudata. so. 48.1.1
/usr/lib/libwireshark.so.1.1.7
/usr/lib/i386-linux-gnu/libQtGui.so.4.8.1
/usr/lib/libwebkitgtk-1.0.so.0.13.4
Пример из листинга ниже содержит две вложенные друг в друга подстановки — подстановку вывода команды date в арифметическую подстановку.
Команда find при поиске модифицированных (-mtine, modification time) файлов использует единицы измерения «дней назад», и при поиске файлов в каталоге /var/lib/dpkg/info (это база данных пакетного менеджера dpkg(1) об установленных в систему пакетах программного обеспечения), изменившихся в период с 20.12.2018 по. 25.12.2018 приходится рассчитывать количество «дней назад» до этих дат.
Для расчета используются команда date и W:[UNIX-время], вычисляющая как целое количество секунд, прошедших от 01.01.1970 00:00 UTC до нужного момента, и арифметическая подстановка, вычисляющая количество «дней назад».
Сначала вычисляется количество «секунд назад» как разница между текущим UNIX-временем и UNIX-временем указанной даты, после чего вычисляется количество «дней назад» путем деления на 60 секунд в минуте, 60 минут в часе и 24 часа в дне. При помощи команды stat подтверждается правильность поиска путем анализа даты модификации найденных файлов.
Пакеты программного обеспечения, установленные в определенный период
bender@ubuntu:~$ set -x
bender@ubuntu:~$ find /var/lib/dpkg/info -name ‘ *.list’ \ ↵
> -mtime -$[ ($(date+%s — $(date-d 2018-12-26 +%s))/ (24*66*60) ] \ ↵
> -mtim -$[ ($(date+%s — $(date-d 2018-12-20 +%s)) / (24*60*60) ] | ↵
> xargs stat -c %y:%n
+ xargs stat -c %y:%n
++ date +%s
++ date -d 2018-12-25 +%s ++ date +%s
++ date -d 2018-12-20 +%s
+ find /var/lib/dpkg/info -name ‘*.list’ -mtine +1 -mtime -6 »
2018-12-24 15:59:50.697681116 +0300: /var/lib/dpkg/info/flex. list
2018-12-20 18:02:51.656846947 +0300:/var/lib/dpkg/info/bison. list
В этом примере строка первой команды конвейера для удобства ввода разбивается на три экранные строки посредством экранирования (см. ниже) управляющего символа перевода строки ↵ при помощи метасимвола одиночного экранирования \.
В этом случае командный интерпретатор каждую последующую экранную строку предваряет «вторичным» приглашением PS2, а не «первичным» приглашением PS1. Символ перевода строки после символа конвейера | экранирования не требует, т. к. командному интерпретатору очевидна необходимость ввода второй команды конвейера.