- Аргументы командной строки в shell-скриптах
- Что такое аргумент командной строки?
- Как сценарии оболочки понимают аргументы командной строки?
- Чтение аргументов командной строки в shell-скриптах
- Подводим итоги
- Разбираемся с аргументами в Bash-скриптах
- Позиционные и специальные параметры
- $1, $2, $3, …: позиционные параметры
- $0: имя скрипта
- $#: число аргументов
- $?: последний код возврата
- $@ and $*: все аргументы
- Итоги
Аргументы командной строки в shell-скриптах
В сегодняшней статье мы разберем чтение аргументов командной строки в сценариях оболочки. Shell-скрипты — инструмент, необходимый любому пользователю Linux. Они играют важную роль в автоматизации повседневных задач и создании собственных команд и макросов.
Сценарии оболочки могут получать ввод от пользователя в виде аргументов.
Когда мы передаем shell-скрипту аргументы, мы можем с их помощью задавать локальную последовательность выполнения задач. Эти аргументы можно применять для получения выходных данных и даже изменять вывод как переменные в сценариях оболочки.
Что такое аргумент командной строки?
Аргументы командной строки — это параметры, которые передаются скрипту во время его выполнения в оболочке bash.
В Linux они также известны как позиционные параметры.
Аргументы командной строки используются для обозначения позиции в памяти, где хранится команда и связанные с ней параметры. Понимание аргументов очень важно для тех, кто изучает сценарии командной строки.
В этой статье мы рассмотрим само понятие аргументов командной строки, а также их использование в shell-скриптах.
Как сценарии оболочки понимают аргументы командной строки?
Аргументы командной строки позволяют делать сценарии оболочки интерактивными для пользователей. Кроме того, они помогают скрипту определить данные, с которыми ему нужно работать. Таким образом, аргументы являются неотъемлемой частью любого практического использования shell-скриптов.
В оболочке bash есть специальные переменные, зарезервированные для указания на аргументы, которые мы передаем через shell-скрипт. Bash сохраняет эти переменные в числовом виде ($1, $2, $3, … $n).
Первый аргумент командной строки в shell-скрипте — $1, второй — $2, третий — $3. И так продолжается до 9-го аргумента. В переменной $0 хранится название скрипта или самой команды.
Также существуют специальные символы, которые являются позиционными параметрами, но их функция тесно связана с аргументами командной строки.
Специальный символ $# хранит общее количество аргументов. Подстановочные символы $@ и $* указывают на все аргументы. $$ используется для поиска идентификатора процесса текущего скрипта оболочки, а $? можно использовать для вывода кода завершения сценария.
Чтение аргументов командной строки в shell-скриптах
Теперь вы имеете представление об аргументах командной строки в Linux. Теперь пришло время использовать эти знания на практике.
В этом туториале применение аргументов командной строки в shell-скрипте мы рассмотрим на примере команды netstat.
Сначала давайте напишем простой сценарий оболочки, чтобы показать работу всех зарезервированных переменных, которые обсуждались ранее. Используйте nano или любой другой редактор для создания файла и скопируйте в него следующий код. Для примера мы планируем использовать вот такой скрипт:
#!/bin/sh echo "Script Name: $0" echo "First Parameter of the script is $1" echo "The second Parameter is $2" echo "The complete list of arguments is $@" echo "Total Number of Parameters: $#" echo "The process ID is $$" echo "Exit code for the script: $?"
После завершения работы сохраним скрипт под названием PositionalParameters.sh и выйдем из текстового редактора.
Теперь давайте откроем командную строку и запустим сценарий оболочки со следующими аргументами.
./PositionalParameters.sh learning command line arguments
Сценарий запустится с указанными аргументами и будет использовать позиционные параметры для вывода данных. Если вы правильно все выполнили, вы увидите следующее:
Вывод показывает ожидаемый результат, заменяя зарезервированные переменные соответствующим аргументом.
Процесс был запущен под идентификатором 14974 и завершен с кодом 0.
Подводим итоги
Читать аргументы командной строки в shell-скриптах — важный навык, поскольку он позволяет нам создавать сценарии, которые могут принимать входные данные от пользователя и логическим путем генерировать выход.
С помощью аргументов в скриптах вы можете значительно упростить повторяющиеся задачи, с которыми вам приходится сталкиваться ежедневно, а также создавать собственные команды, экономя при этом время и силы.
Разбираемся с аргументами в Bash-скриптах
Перевод статьи «Handling Arguments in Bash Scripts».
Создание Bash-скриптов для автоматизации набора команд — первый шаг на пути к созданию инструментов, облегчающих вашу жизнь. Даже простые скрипты, читающиеся сверху вниз и запускающиеся по установленному графику, способны сэкономить вам массу времени. Но рано или поздно наступит момент, когда вы захотите настраивать поведение вашего скрипта на лету: создавать директории с нужными вам именами, загружать файлы из определенных git-репозиториев, указывать IP-адреса или порты и т. п. Вот здесь вам и пригодятся аргументы скриптов.
Позиционные и специальные параметры
Bash предоставляет нам переменные, которые присутствуют в любом написанном нами скрипте. Вот несколько самых полезных:
$1, $2, $3, …: позиционные параметры
Позиционные параметры содержат значения, которые вы указываете при запуске своего скрипта (в командной строке) в качестве аргументов. Рассмотрим пример. Допустим, у вас есть скрипт, запускающийся следующим образом:
Переменная $1 будет содержать значение «200», а переменная $2 — значение «goats».
Я использую позиционные параметры в одном из своих простейших скриптов. Этот скрипт я запускаю на работе практически ежедневно (здесь показываю упрощенный вариант):
!/usr/bin/env bash project_name="$1" mkdir -p "$/" echo "New project '$project_name' created!"
Как видите, я беру позиционную переменную $1 и сохраняю ее значение в настоящей именованной переменной. Но делать так не обязательно. Я мог бы написать
и все равно все бы прекрасно работало.
Тем не менее, я предпочитаю сохранять позиционные параметры в именованные переменные вверху своего скрипта. Таким образом любой читатель моего скрипта сможет быстро понять, что к чему. Разумеется, это не заменяет хорошую документацию и надежную обработку ошибок, но это приятный маленький бонус в плане читаемости. Подобные вещи хоть немножко, но помогают, так что это хорошая практика.
Когда я запускаю скрипт вот так:
он генерирует структуру директорий:
catheter-01 |- CAD |- drawings |- mold |- resources
$0: имя скрипта
В позиционной переменной $0 при вызове скрипта сохраняется его имя. Это особенно полезно для вывода сообщений о том, как нужно использовать этот скрипт.
#!/usr/bin/env bash function usage() < echo "Usage: $0 [options]" > # Error handling omitted (for now) if [[ "$1" == -h ]]; then usage exit 0 fi name="$1" echo "Hello, $!"
Вот что получится при запуске:
$ ./greeting -h Usage: ./greeting [options] $ bash greeting -h Usage: greeting [options] $ ./greeting "Ryan" Hello, Ryan!
$#: число аргументов
Кроме позиционных параметров в Bash есть еще и специальные. Переменная $# хранит количество аргументов, переданных через командную строку. Это очень пригождается в обработке ошибок. Что произойдет, если наш скрипт не получит нужных ему аргументов? Давайте обновим скрипт из предыдущего примера и добавим обработку ошибок.
#!/usr/bin/env bash function usage() < echo "Usage: $0 [options]" > ### Hot new error handling! # We expect one argument. Otherwise tell the user how to # call your script. if [[ "$#" -ne 1 ]]; then usage exit 1 fi if [[ "$1" == -h ]]; then usage exit 0 fi name="$1" echo "Hello, $!"
$?: последний код возврата
Лично я нечасто пользуюсь этим специальным параметром в скриптах, зато интенсивно использую его в командной строке. Многие команды, когда их выполнение проваливается, не выводят никаких сообщений. Они просто ничего не делают. Как же вам узнать, успешно ли отработала команда? Можно вывести значение переменной $? , в которой сохраняется код возврата последней запускавшейся команды.
$ ls test.txt code strudel.py $ echo $? 0 $ ls lamedir ls: cannot access 'lamedir': No such file or directory $ echo $? 2
Вот пример использования в скрипте:
#!/usr/bin/env bash dirname="$1" mkdir "$dirname" # This will fail if the directory exists already if [[ "$?" -ne 0 ]]; then # If the directory is already created, that's fine # just print out a message to alert the user echo "Directory '$dirname' already exists. Not making a new one." fi
$@ and $*: все аргументы
Кажется, именно эти переменные вызывают больше всего сложностей у новичков в Bash — и это понятно! Они работают практически одинаково, но разница в их действии может быть очень существенной в каждой отдельной ситуации.
Если вы НЕ берете эти переменные в кавычки, они делают одно и то же: вставляют в указанное место все переданные в скрипт аргументы.
#!/usr/bin/env bash echo "====================" echo "This is dollar star." echo "====================" for arg in $*; do echo "$arg" done echo "====================" echo "This is dollar at." echo "====================" for arg in $@; do echo "$arg" done
При запуске получим следующее:
$ ./arg_printer abba dabba "dooby doo" ==================== This is dollar star. ==================== abba dabba dooby doo ==================== This is dollar at. ==================== abba dabba dooby doo
Обратите внимание на аргумент «dooby doo» . Он был взят в кавычки при передаче, но в результате разбился по пробелу на два разных аргумента. Порой это именно то, что нужно, но очень часто — нет.
Переходим к самому интересному: возьмем переменные в кавычки.
Если взять в кавычки $* , в выводе вы получите все аргументы в одной строке. Аргументы будут разделены пробелами и фактически станут одним аргументом. Причем это не зависит от того, были ли они заключены в кавычки при вводе.
Примечание. На самом деле аргументы разделяются $IFS («внутренним разделителем полей»). Обычно это пробел, но стоит знать, что так бывает не всегда.
#!/usr/bin/env bash echo "====================" echo "This is quoted dollar star." echo "====================" for arg in "$*"; do echo "$arg" done
$ ./arg_printer abba dabba "dooby doo" ==================== This is quoted dollar star. ==================== abba dabba dooby doo
Видите? Один аргумент! Хотите самостоятельно реализовать echo?
$ ./my_echo hello my name is Ryan hello my name is Ryan
А вот когда вы берете в кавычки $@ , Bash выводит все аргументы так, как они были переданы изначально. Это, на мой взгляд, самый полезный функционал, потому что позволяет передавать все аргументы подкомандам, сохраняя при этом пробелы и кавычки и не позволяя автоматическому разделению строк Bash все испортить.
#!/usr/bin/env bash echo "====================" echo "This is quoted dollar at." echo "====================" for arg in "$@"; do echo "$arg" done
$ ./arg_printer abba dabba "dooby doo" ==================== This is quoted dollar at. ==================== abba dabba dooby doo
Вы часто увидите это в скриптах, содержащих множество функций. Традиционно, если у вас много функций, вы делаете последнюю функцию в скрипте функцией main . Она будет обрабатывать все аргументы и содержать организационную логику скрипта. А для запуска функции main обычно последней строчкой скрипта идет main «$@» . Вот так:
#!/usr/bin/env bash function usage() < echo "Usage: $0 [options]" > function bigger() < local first="$1" local second="$2" if [[ "$first" -gt "$second" ]]; then echo "$first" else echo "$second" fi >function main() < if [[ "$#" -ne 2 ]]; then usage exit 1 fi local first="$1" local second="$2" bigger "$first" "$second" >main "$@"
Итоги
Надеюсь, теперь вы начинаете понимать силу кастомизации. Используя скрипты Bash, вы можете автоматизировать выполнение многих задач. А благодаря возможности передачи аргументов при вызове скрипта вы можете автоматически выполнять даже те задачи, логика которых зависит от ситуации!