вцуйф ауцй. Bash скрипты
Скачать 3.58 Mb.
|
Подсчёт параметров В скрипте можно подсчитать количество переданных ему параметров. Оболочка bash предоставляет для этого специальную переменную. А именно, переменная $# содержит количество параметров, переданных сценарию при вызове. Опробуем е #!/bin/bash echo There were $# parameters passed. Вызовем сценарий. ./myscript 1 2 3 4 5 В результате скрипт сообщит о том, что ему передано 5 параметров. Подсчёт количества параметров в скрипте Эта переменная даёт необычный способ получения последнего из переданных скрипту параметров, не требующий знания их количества. Вот как это выглядит #!/bin/bash echo The last parameter was ${!#} Вызовем скрипт и посмотрим, что он выведет. 33 Обращение к последнему параметру Захват всех параметров командной строки В некоторых случаях нужно захватить все параметры, переданные скрипту. Для этого можно воспользоваться переменными $* и $@. Обе они содержат все параметры командной строки, что делает возможным доступ к тому, что передано сценарию, без использования позиционных параметров. Переменная $* содержит все параметры, введённые в командной строке, в виде единого слова. В переменной $@ параметры разбиты на отдельные слова. Эти параметры можно перебирать в циклах. Рассмотрим разницу между этими переменными на примерах. Сначала взглянем на их содержимое #!/bin/bash echo "Using the \$* method: $*" echo "-----------" echo "Using the \$@ method: $@" Вот вывод скрипта. Переменные $* и $@ Как видно, при выводе обеих переменных получается одно и тоже. Теперь попробуем пройтись по содержимому этих переменных в циклах для того, чтобы увидеть разницу между ними #!/bin/bash count=1 for param in "$*" do echo "\$* Parameter #$count = $param" count=$(( $count + 1 )) done count=1 for param in "$@" 34 do echo "\$@ Parameter #$count = $param" count=$(( $count + 1 )) done Взгляните на то, что скрипт вывел в консоль. Разница между переменными вполне очевидна. Разбор переменных $* ив цикле Переменная $* содержит все переданные скрипту параметры как единый фрагмент данных, в то время как в переменной $@ они представлены самостоятельными значениями. Какой именно переменной воспользоваться — зависит оттого, что именно нужно в конкретном сценарии. Команда shift Использовать команду shift в скриптах следует с осторожностью, так как она, в прямом смысле слова, сдвигает значения позиционных параметров. Когда вы используете эту команду, она, по умолчанию, сдвигает значения позиционных параметров влево. Например, значение переменной $3 становится значением переменной $2, значение $2 переходит в $1, а то, что было до этого в $1, теряется. Обратите внимание на то, что при этом значение переменной $0, содержащей имя скрипта, не меняется. Воспользовавшись командой shift, рассмотрим ещё один способ перебора переданных скрипту параметров #!/bin/bash count=1 while [ -n "$1" ] do echo "Parameter #$count = $1" count=$(( $count + 1 )) shift done Скрипт задействует цикл while, проверяя длину значения первого параметра. Когда длина станет равна нулю, происходит выход из цикла. После проверки первого параметра и вывода его на экран, вызывается команда shift, которая сдвигает значения параметров на одну позицию. 35 Использование команды shift для перебора параметров Используя команду shift, помните о том, что при каждом её вызове значение переменной $1 безвозвратно теряется. Ключи командной строки Ключи командной строки обычно выглядят как буквы, перед которыми ставится тире. Они служат для управления сценариями. Рассмотрим такой пример #!/bin/bash echo while [ -n "$1" ] do case "$1" in -a) echo "Found the -a option" ;; -b) echo "Found the -b option" ;; -c) echo "Found the -c option" ;; *) echo "$1 is not an option" ;; esac shift done Запустим скрипт $ ./myscript –a –b –c –d И проанализируем то, что он выведет в терминал. Обработка ключей в скрипте 36 В этом коде использована конструкция case, которая сверяет переданный ей ключ со списком обрабатываемых скриптом ключей. Если переданное значение нашлось в этом списке, выполняется соответствующая ветвь кода. Если при вызове скрипта будет использован любой ключ, обработка которого не предусмотрена, будет исполнена ветвь «*». Как различать ключи и параметры Часто при написании скриптов возникает ситуация, когда надо использовать и параметры командной строки, и ключи. Стандартный способ это сделать заключается в применении специальной последовательности символов, которая сообщает скрипту о том, когда заканчиваются ключи и начинаются обычные параметры. Эта последовательность — двойное тире (--). Оболочка используете для указания позиции, на которой заканчивается список ключей. После того, как скрипт обнаружит признак окончания ключей, то, что осталось, можно, не опасаясь ошибок, обрабатывать как параметры, а не как ключи. Рассмотрим пример #!/bin/bash while [ -n "$1" ] do case "$1" in -a) echo "Found the -a option" ;; -b) echo "Found the -b option";; -c) echo "Found the -c option" ;; --) shift break ;; *) echo "$1 is not an option";; esac shift done count=1 for param in $@ do echo "Parameter #$count: $param" count=$(( $count + 1 )) done Этот сценарий использует команду break для прерывания цикла while при обнаружении в строке двойного тире. Вот что получится после его вызова. 37 Обработка ключей и параметров командной строки Как видно, когда скрипт, разбирая переданные ему данные, находит двойное тире, он завершает обработку ключей и считает всё, что ещё не обработано, параметрами. Обработка ключей со значениями По мере усложнения ваших скриптов, вы столкнётесь с ситуациями, когда обычных ключей уже недостаточно, а значит, нужно будет использовать ключи с некими значениями. Например, вызов сценария в котором используется подобная возможность, выглядит так ./myscript -a test1 -b -c test2 Скрипт должен уметь определять, когда вместе с ключами командной строки используются дополнительные параметры #!/bin/bash while [ -n "$1" ] do case "$1" in -a) echo "Found the -a option";; -b) param="$2" echo "Found the -b option, with parameter value $param" shift ;; -c) echo "Found the -c option";; --) shift break ;; *) echo "$1 is not an option";; esac shift done count=1 for param in "$@" 38 do echo "Parameter #$count: $param" count=$(( $count + 1 )) done Вызовем этот скрипт в таком виде ./myscript -a -b test1 -d Посмотрим на результаты его работы. Обработка параметров ключей В данном примере в конструкции case обрабатываются три ключа. Ключ -b требует наличия дополнительного параметра. Так как обрабатываемый ключ находится в переменной $1, соответствующий ему параметр будет находиться в $2 (тут используется команда shift, поэтому, по мере обработки, всё, что передано сценарию, сдвигается влево. Когда с этим мы разобрались, осталось лишь извлечь значение переменной $2 и у нас будет параметр нужного ключа. Конечно, тут понадобится ещё одна команда shift для того, чтобы следующий ключ попал в $1. Использование стандартных ключей При написании скриптов вы можете выбирать любые буквы для ключей командной строки и произвольно задавать реакцию скрипта на эти ключи. Однако, в мире Linux значения некоторых ключей стали чем-то вроде стандарта, которого полезно придерживаться. Вот список этих ключей - a Вывести все объекты. - c Произвести подсчёт. - d Указать директорию. - e Развернуть объект. - f Указать файл, из которого нужно прочитать данные. - h Вывести справку по команде. - i Игнорировать регистр символов. - l Выполнить полноформатный вывод данных. - n Использовать неинтерактивный (пакетный) режим. - o Позволяет указать файл, в который нужно перенаправить вывод. - q Выполнить скрипт в режиме. - r Обрабатывать папки и файлы рекурсивно. - s Выполнить скрипт в режиме. - v Выполнить многословный вывод. - x Исключить объект. - y Ответить «yes» на все вопросы. 39 Если выработаете в Linux, вам, скорее всего, знакомы многие из этих ключей. Использовав их в общепринятом значении в своих скриптах, вы поможете пользователям взаимодействовать сними, не беспокоясь о чтении документации. Получение данных от пользователя Ключи и параметры командной строки — это отличный способ получить данные оттого, кто пользуется скриптом, однако в некоторых случаях нужно больше интерактивности. Иногда сценарии нуждаются в данных, которые пользователь должен ввести вовремя выполнения программы. Именно для этой цели в оболочке bash имеется команда read. Эта команда позволяет принимать введённые данные либо со стандартного ввода (с клавиатуры, либо используя другие дескрипторы файлов. После получения данных, эта команда помещает их в переменную #!/bin/bash echo -n "Enter your name: " read name echo "Hello $name, welcome to my program." Обратите внимание на то, что команда echo, которая выводит приглашение, вызывается с ключом -n. Это приводит к тому, что в конце приглашения не выводится знак перевода строки, что позволяет пользователю скрипта вводить данные там же, где расположено приглашение, а не наследующей строке. Обработка пользовательского ввода При вызове read можно указывать и несколько переменных #!/bin/bash read -p "Enter your name: " first last echo "Your data for $last, $first…" Вот что выведет скрипт после запуска. Несколько переменных в команде read 40 Если, вызвав read, не указывать переменную, данные, введённые пользователем, будут помещены в специальную переменную среды REPLY: #!/bin/bash read -p "Enter your name: " echo Hello $REPLY, welcome to my program. Использование переменной среды REPLY Если скрипт должен продолжать выполнение независимо оттого, введёт пользователь какие-то данные или нет, вызывая команду read можно воспользоваться ключом -t. А именно, параметр ключа задаёт время ожидания ввода в секундах #!/bin/bash if read -t 5 -p "Enter your name: " name then echo "Hello $name, welcome to my script" else echo "Sorry, too slow! " fi Если данные не будут введены в течение 5 секунд, скрипт выполнит ветвь условного оператора else, выведя извинения. Ограничение времени на ввод данных Ввод паролей Иногда то, что вводит пользователь в ответ на вопрос скрипта, лучше на экране не показывать. Например, так обычно делают, запрашивая пароли. Ключ -s команды read предотвращает отображение на экране данных, вводимых с клавиатуры. На самом деле, данные выводятся, но команда read делает цвет текста таким же, как цвет фона. #!/bin/bash read -s -p "Enter your password: " pass echo "Is your password really $pass? " 41 Вот как отработает этот скрипт. Ввод конфиденциальных данных Чтение данных из файла Команда read может, при каждом вызове, читать одну строку текста из файла. Когда в файле больше не останется непрочитанных строк, она просто остановится. Если нужно получить в скрипте всё содержимое файла, можно, с помощью конвейера, передать результаты вызова команды cat для файла, конструкции while, которая содержит команду read (конечно, использование команды cat выглядит примитивно, но наша цель — показать всё максимально просто, ориентируясь на новичков опытные пользователи, уверены, это поймут. Напишем скрипт, в котором используется только что описанный подход к чтению файлов. #!/bin/bash count=1 cat myfile | while read line do echo "Line $count: $line" count=$(( $count + 1 )) done echo "Finished" Посмотрим на него в деле. Чтение данных из файла Тут мы передали в цикл while содержимое файла и перебрали все строки этого файла, выводя номер и содержимое каждой из них. Итоги Сегодня мы разобрали работу с ключами и параметрами командной строки. Без этих средств диапазон использования скриптов оказывается чрезвычайно узким. Даже если скрипт написан, что называется, для себя. Тут же мы рассмотрели подходы к получению данных от пользователя вовремя выполнения программы — это делает сценарии интерактивными. 42 В следующий раз поговорим об операциях ввода и вывода. 43 скрипты, часть 4: вводи вывод В прошлый разв третьей части этой серии материалов по скриптам, мы говорили о параметрах командной строки и ключах. Наша сегодняшняя тема — ввод, выводи всё, что с этим связано. Вы уже знакомы с двумя методами работы стем, что выводят сценарии командной строки ● Отображение выводимых данных на экране. ● Перенаправление вывода в файл. Иногда что-то надо показать на экране, а что-то — записать в файл, поэтому нужно разобраться стем, как в Linux обрабатывается вводи вывода значит — научиться отправлять результаты работы сценариев туда, куда нужно. Начнём с разговора о стандартных дескрипторах файлов. Стандартные дескрипторы файлов Всё в Linux — это файлы, в том числе — вводи вывод. Операционная система идентифицирует файлы с использованием дескрипторов. Каждому процессу позволено иметь до девяти открытых дескрипторов файлов. Оболочка bash резервирует первые три дескриптора с идентификаторами 0, 1 и 2. Вот что они означают. ● 0, STDIN — стандартный поток ввода. ● 1, STDOUT — стандартный поток вывода. ● 2, STDERR — стандартный поток ошибок. Эти три специальных дескриптора обрабатывают вводи вывод данных в сценарии. Вам нужно как следует разобраться в стандартных потоках. Их можно сравнить с фундаментом, на котором строится взаимодействие скриптов с внешним миром. Рассмотрим подробности о них. STDIN STDIN — это стандартный поток ввода оболочки. Для терминала стандартный ввод — это клавиатура. Когда в сценариях используют символ перенаправления ввода — <, Linux заменяет дескриптор файла стандартного ввода на тот, который указан в команде. Система читает файл и обрабатывает данные так, будто они введены с клавиатуры. Многие команды bash принимают ввод из STDIN, если в командной строке не указан файл, из которого надо брать данные. Например, это справедливо для команды cat. Когда вы вводите команду cat в командной строке, не задавая параметров, она принимает ввод из STDIN. После того, как вы вводите очередную строку, cat просто выводите на экран. STDOUT STDOUT — стандартный поток вывода оболочки. По умолчанию это — экран. Большинство bash- команд выводят данные в STDOUT, что приводит к их появлению в консоли. Данные можно перенаправить в файл, присоединяя их к его содержимому, для этого служит команда >>. 44 Итаку насесть некий файл сданными, к которому мы можем добавить другие данные с помощью этой команды pwd >> myfile То, что выведет pwd, будет добавлено к файлу myfile, при этом уже имеющиеся в нём данные никуда не денутся. Перенаправление вывода команды в файл Пока всё хорошо, но что если попытаться выполнить что-то вроде показанного ниже, обратившись к несуществующему файлу xfile, задумывая всё это для того, чтобы в файл myfile попало сообщение об ошибке. ls –l xfile > myfile После выполнения этой команды мы увидим сообщения об ошибках на экране. Попытка обращения к несуществующему файлу При попытке обращения к несуществующему файлу генерируется ошибка, но оболочка не перенаправила сообщения об ошибках в файл, выведя их на экран. Но мыто хотели, чтобы сообщения об ошибках попали в файл. Что делать Ответ прост — воспользоваться третьим стандартным дескриптором. STDERR STDERR представляет собой стандартный поток ошибок оболочки. По умолчанию этот дескриптор указывает на тоже самое, на что указывает STDOUT, именно поэтому при возникновении ошибки мы видим сообщение на экране. Итак, предположим, что надо перенаправить сообщения об ошибках, скажем, в лог-файл, или куда- нибудь ещё, вместо того, чтобы выводить их на экран. Перенаправление потока ошибок Как вы уже знаете, дескриптор файла STDERR — 2. Мы можем перенаправить ошибки, разместив этот дескриптор перед командой перенаправления: ls -l xfile 2>myfile cat ./myfile 45 Сообщение об ошибке теперь попадёт в файл myfile. Перенаправление сообщения об ошибке в файл Перенаправление потоков ошибок и вывода При написании сценариев командной строки может возникнуть ситуация, когда нужно организовать и перенаправление сообщений об ошибках, и перенаправление стандартного вывода. Для того, чтобы этого добиться, нужно использовать команды перенаправления для соответствующих дескрипторов с указанием файлов, куда должны попадать ошибки и стандартный вывод ls –l myfile xfile anotherfile 2> errorcontent 1> correctcontent Перенаправление ошибок и стандартного вывода Оболочка перенаправит то, что команда ls обычно отправляет в STDOUT, в файл correctcontent благодаря конструкции 1>. Сообщения об ошибках, которые попали бы в STDERR, оказываются в файле errorcontent из-за команды перенаправления 2>. Если надои, и STDOUT можно перенаправить в один и тот же файл, воспользовавшись командой &>: Перенаправление STDERR ив один и тот же файл После выполнения команды то, что предназначено для STDERR и STDOUT, оказывается в файле content. Перенаправление вывода в скриптах Существует два метода перенаправления вывода в сценариях командной строки ● Временное перенаправление, или перенаправление вывода одной строки. 46 ● Постоянное перенаправление, или перенаправление всего вывода в скрипте либо в какой-то его части. Временное перенаправление вывода В скрипте можно перенаправить вывод отдельной строки в STDERR. Для того, чтобы это сделать, достаточно использовать команду перенаправления, указав дескриптор STDERR, при этом перед номером дескриптора надо поставить символ амперсанда (&): #!/bin/bash echo "This is an error" >&2 echo "This is normal output" Если запустить скрипт, обе строки попадут на экран, так как, как вы уже знаете, по умолчанию ошибки выводятся туда же, куда и обычные данные. Временное перенаправление Запустим скрипт так, чтобы вывод STDERR попадал в файл. ./myscript 2> myfile Как видно, теперь обычный вывод делается в консоль, а сообщения об ошибках попадают в файл. Сообщения об ошибках записываются в файл Постоянное перенаправление вывода Если в скрипте нужно перенаправлять много выводимых на экран данных, добавлять соответствующую команду к каждому вызову echo неудобно. Вместо этого можно задать перенаправление вывода в определённый дескриптор на время выполнения скрипта, воспользовавшись командой exec: #!/bin/bash exec 1>outfile echo "This is a test of redirecting all output" echo "from a shell script to another file." echo "without having to redirect every line" Запустим скрипт. 47 Перенаправление всего вывода в файл Если просмотреть файл, указанный в команде перенаправления вывода, окажется, что всё, что выводилось командами echo, попало в этот файл. Команду exec можно использовать не только вначале скрипта, но ив других местах #!/bin/bash exec 2>myerror echo "This is the start of the script" echo "now redirecting all output to another location" exec 1>myfile echo "This should go to the myfile file" echo "and this should go to the myerror file" >&2 Вот что получится после запуска скрипта и просмотра файлов, в которые мы перенаправляли вывод. Перенаправление вывода в разные файлы Сначала команда exec задаёт перенаправление вывода изв файл myerror. Затем вывод нескольких команд echo отправляется в STDOUT и выводится на экран. После этого команда exec задаёт отправку того, что попадает в STDOUT, в файл myfile, и, наконец, мы пользуемся командой перенаправления в STDERR в команде echo, что приводит к записи соответствующей строки в файл myerror. Освоив это, вы сможете перенаправлять вывод туда, куда нужно. Теперь поговорим о перенаправлении ввода. |