Сценарии командной оболочки. Linux, OS X и Unix. 2-е издание - страница 11
Как это работает
Функция checkForCmdInPath отличает значение параметра с одним только именем программы (например, echo) от значения, содержащего полный путь, плюс имя файла (например, /bin/echo). Для этого она сравнивает первый символ в переданном ей значении с символом /; для чего ей требуется изолировать первый символ от остального значения параметра.
Обратите внимание на синтаксис ${var:0:1}
>$ var="something wicked this way comes…"
>$ echo ${var:10}
>wicked this way comes…
>$ echo ${var:10:6}
>wicked
>$
В листинге 1.1 данный синтаксис используется, чтобы определить, начинается ли указанный путь с символа слеша. Если это так, то далее функция проверяет наличие указанного файла в файловой системе по указанному пути. Пути, начинающиеся с символа /, являются абсолютными, и для их проверки можно использовать оператор −x
Запуск сценария
Чтобы запустить сценарий как самостоятельную программу, нужно добавить в самый конец файла короткий блок команд. Эти команды просто принимают ввод пользователя и передают его в функцию, как показано ниже.
>if [$# −ne 1]; then
>··echo "Usage: $0 command" >&2
>··exit 1
>fi
>checkForCmdInPath "$1"
>case $? in
>··0) echo "$1 found in PATH";;
>··1) echo "$1 not found or not executable";;
>··2) echo "$1 not found in PATH";;
>esac
>exit 0
После добавления кода сценарий можно запустить непосредственно, как показано далее, в разделе «Результаты». Закончив эксперименты со сценарием, не забудьте удалить или закомментировать дополнительный код, чтобы потом его можно было подключать как библиотеку функций.
Результаты
Для проверки вызовем сценарий inpath с именами трех программ: существующей программы, также существующей программы, но находящейся в каталоге, не включенном в список PATH, и несуществующей программы, но с полным путем к ней. Пример тестирования сценария приводится в листинге 1.2.
Листинг 1.2. Тестирование сценария inpath
>$ inpath echo
>echo found in PATH
>$ inpath MrEcho
>MrEcho not found in PATH
>$ inpath /usr/bin/MrEcho
>/usr/bin/MrEcho not found or not executable
Последний блок кода, добавленный позднее, преобразует результат вызова функции in_path в нечто более читаемое, поэтому теперь мы легко можем видеть, что все три случая обрабатываются, как ожидалось.
Усовершенствование сценария
Для желающих начать овладевать мастерством программирования с первого сценария, покажем, как заменить выражение ${var:0:1} его более сложной формой: ${var%${var#?}}. Такой метод извлечения подстрок определяет стандарт POSIX. Эта галиматья в действительности включает два выражения извлечения подстроки. Внутреннее выражение ${var#?} извлекает из var все, кроме первого символа, где # удаляет первое совпадение с заданным шаблоном, а? — это регулярное выражение, которому соответствует точно один символ.
Внешнее выражение ${var%pattern} возвращает подстроку из строки слева, оставшуюся после удаления указанного шаблона pattern из var. В данном случае удаляемый шаблон pattern — это результат внутреннего выражения, то есть внешнее выражение вернет первый символ в строке.
Для тех, кому POSIX-совместимый синтаксис кажется пугающим, отметим, что большинство командных оболочек (включая bash, ksh и zsh) поддерживает другой метод извлечения подстрок, ${varname: start: size}, который был использован в сценарии.
Те, кому не нравится ни один из представленных способов извлечения первого символа, могут использовать системные команды: $(echo $var | cut −c1). В программировании на bash практически любую задачу, будь то извлечение, преобразование или загрузка данных из системы, можно решить несколькими способами. При этом важно понимать, что наличие нескольких способов не означает, что один способ лучше другого.