- Параметры команд
- Обработка аргументов командной строки в Bash
- Обработка нескольких аргументов командной строки в shell-скрипте
- Обработка большого количества аргументов командной строки в Bash
- Введение в getopt
- Bash в примерах. Часть вторая.
- Еще больше основ программирования в bash
- Обработка аргументов
- Управляющие конструкции bash
- Оператор условного выбора «if»
- Тонкости при сравнении строк
- Конструкция создания циклов «for»
- Арифметика в shell
- Циклические конструкции с условиями («while» и «until»)
- Экстренный выход из цикла
- Команда–переключатель «case»
- Функции и пространство имен
- Пространство имен
- Подведение итогов
Параметры команд
Большинство команд, используемых в Bash, могут отдаваться как одним словом, так и предполагать после себя какие-либо уточняющие параметры.
Мы будем называть параметрами все, что идет после команды. При этом делить параметры на ключи и аргументы. Ключами будем называть то, чему обычно предшествует один или два знака минуса. Ключи, если присутствуют, ставятся перед аргументами. У команды могут быть как ключи, так и аргументы, так и только ключи или только аргументы.
Обычно аргументы – это то, над чем выполняется команда. Например, команда перехода в другую директорию должна получить в качестве аргумента имя каталога, куда следует перейти. Команде вывода на экран содержимого файла надо передать имя файла.
Ключи модифицируют, как бы видоизменяют работу программы. Например, с помощью команды просмотра содержимого каталога можно вывести простой список вложенных объектов. Используя же определенный ключ, можно получить подробные сведения о каждом файле и папке.
Рассмотрим использование параметров на примере команды ncal, которая выводит на экран календарь. Без параметров она выведет календарь на текущий месяц.
Если мы хотим увидеть календарь за другой месяц, следует передать программе ncal два аргумента: месяц и год.
Если указать только один аргумент, то будет считаться, что передается только год. Будет выведен календарь на целый год.
С помощью ключа -b можно перевернуть календарь на 90 градусов. Понятно, что аргументы могут быть как указаны или нет. В последнем случае получится перевернутый календарь на текущий месяц.
У команд может быть множество ключей. Их можно комбинировать.
В данном случае используется два ключа. Ключ -w приказывает ncal выводить кроме прочего номера недель года. На скриншоте выше ключи записаны вместе. Однако можно было дать команду так: ncal -b -w .
Опция не всегда обозначается маленькой буквой. Бывают ключи, обозначаемые заглавной буквой или словом. В случае слова используется два знака минуса, чтобы Bash понимал, что перед ним не перечень подряд идущих ключей, а только один. В примере ниже опции -V и —version программы python3 делают одно и тоже – выводят версию интерпретатора.
Существуют команды, которые не имеют смысла без аргументов, то есть для них не задано поведение «по-умолчанию». Например, команда sleep, заставляющая bash выполнить задержку перед следующей командой. Время можно указывать в секундах, минутах и др.
Отметим, что понятия «команда», «параметр», «ключ», «аргумент» не являются каким-либо стандартом. В терминологии Bash ключи также называют опциями, аргументы – операндами, то есть тем, над чем выполняется команда.
Однако с точки зрения программирования все, что содержит строка команды, это аргументы. Введенная строка передается программе целиком, где «разрезается» на отдельные слова, которые помещаются в массив, первый элемент которого – имя вызываемой программы. Далее программа так или иначе обрабатывает аргументы, если предполагает работу с ними.
Объясните, что делает команда echo. По результату выполнения echo -e «one\ntwo\tthree» объясните назначение ключа -e.
Курс с ответами к заданиям и дополнительными уроками:
android-приложение, pdf-версия.
Источник
Обработка аргументов командной строки в Bash
Оригинал: Working with Command Arguments by Dave Taylor
Перевод: собственный, вольный с исправлениями
В этой статье будет затронута одна из основных особенностей создания shell-скриптов: обработка аргументов командной строки. Большинство простых сценариев не имеют входных параметров, а по мере развития обзаводятся одним или двумя. Если их становится много, то для обработки аргументов используется getopt. Увеличение сложности может привести и к переписыванию на языках высокого уровня, к примеру, С++ или Ruby.
Самый простой способ обработки аргументов командной строки – установка флага с помощью условного оператора:
if [ «$1» = «-a» ]; then flag_a=1 fi
При реализации такого подхода возникает несколько проблем. Одна из них – захламление исходного кода дополнительными конструкциями. Так, перед этим примером необходимо предварительно обнулить переменную с помощью выражения flag_a=0. Иначе нельзя точно определить, какое значение присвоит ей оболочка командной строки при инициализации.
Другая проблема состоит в том, что выполнение этого блока никак не влияет на параметры командной строки: $1 по-прежнему может быть флагом (-a), другим аргументом или значением, введённым пользователем. Следовательно необходимо будет добавить дополнительные проверки при считывании остальных опций.
Обработка нескольких аргументов командной строки в shell-скрипте
Для наглядности представим, что существует простой скрипт. Он работает в качестве обёртки к чему-то на подобии curl: если передать в него ссылку, то содержимое web-страницы будет скачано и сохранено в файле на локальном диске. К тому же, с помощью воображаемого флага -a можно увидеть ход работы.
Команда для выполнения сценария в bash будет выглядеть следующим образом:
getpage.sh -a http://ozi-blog.ru/
Аргументы командной строки инициализируются в том же порядке: $0 = getpage.sh, $1 = -a, $2 = http://ozi-blog.ru и их общее количество $# = 2.
Стоит помнить, что $# – количество всех аргументов, а не сумма слов в команде. Можно подумать, что если скрипт вызывается без каких-либо параметров, то $# должно равняться 1 (учитывая имя сценария), однако на самом деле $#=0.
Подобная особенность нумерации существует с зари развития UNIX и известна под названием “проблема нулевого индекса”. Так, в массивах первое значение можно получить по индексу 0 или array[0]. Для многих разработчиков это понятно, для других же – вызывает затруднение. Начинающие программисты могут даже игнорировать нулевой индекс в языке C и начинать использовать ячейки массива с 1, а не 0.
После успешной проверки на наличие флага -a для первого аргумента ($1) следует переместить все значения остальных параметров ($2) на одну позицию влево ($1=$2). Тогда в остальной части программы можно будет считать, что в $1 находится адрес ссылки. Отпадает необходимость избыточных проверок на наличие или отсутствие флага.
Это можно сделать с помощью команды сдвига (shift). В итоге получаем правильный способ обработки одного опционального аргумента командной строки в shell-скрипте:
flag_a=0 if [ «$1» = «-a» ]; then flag_a=1 shift fi url=$1
Однако, иногда возникает ситуация, когда за опциональным аргументом следует обязательный. К примеру, дополним наш воображаемый скрипт флагом -o, после которого необходимо указать путь к файлу для сохранения страницы.
Решить эту задачу можно немного изменив предыдущий пример:
outputspecified=0 if [ «$1» = «-o» ]; then outputspecified=1 outputfilename=»$2″ shift 2 fi
Таким образом, команда shift принимает одно число. Оно указывает на сколько позиций необходимо сдвинуть значения аргументов командной строки. Это легко продемонстрировать, если вывести их до и после выполнения блока кода с shift 2:
$ sh getpage.sh -o test.html какая-то-ссылка $# = 3 $1 = -o $2 = test.html $3 = какая-то-ссылка —— выполнение команды shift 2 —— $# = 1 $1 = какая-то ссылка $2 = $3 =
Изначально все три аргумента заданы и их количество ($#) равно 3. После выполнения shift 2 все значения сместились на две позиции и их количество также уменьшилось.
Дальнейшее увеличение количества входных параметров значительно усложнит код, потребуется другой подход.
Обработка большого количества аргументов командной строки в Bash
Даже обработка двух флагов сопряжена с трудностями. Качества кода выше значительно ухудшится, если аргументы могут указываться в произвольном порядке. Но даже без этого, для обработки трёх стартовых условий (-a, -c, -o) перед операцией сдвига понадобится проверка всех вариантов. Потом еще раз проверка и сдвиг. И еще раз проверка и сдвиг. Кроме того, пользователи любят комбинировать опции запуска программы между собой. Представьте, как ужасно разбирать на составные части входные данные вида -ac -o или -aco.
Введение в getopt
Если необходимо создать объёмный сценарий с большим набором опций запуска, то использование программы getopt – одно из лучших решений. С помощью этой утилиты можно легко разобрать на составные части различные флаги и значения, скомбинировать их, а затем обработать удобным способом в одном месте.
Алгоритм применения getopt выглядит следующим образом:
- Разбор существующих аргументов командной строки с помощью getopt. В результате будет создана временная переменная с отсортированными данными по заданному шаблону.
- Замена аргументов на новые командой set.
- Последовательная обработка полученных значений в цикле.
Наглядно продемонстрировать эту последовательность действий можно на простом примере. Предположим, что существует скрипт, ход выполнения которого задаётся тремя опциями: -s, -p и –t.
Вначале необходимо привести аргументы командной строки к структурированному виду командой getopt. Это поможет избавиться от влияния способа ввода данных пользователем:
При сравнении с обработкой ошибок (показана ниже) можно заметить, что первый параметр для getopt – это список всех допустимых флагов. С помощью : указывается, что после аргумента следует еще один обязательный.
Затем можно проверить значение переменной $? – статус выполнения последней операции. Если при обработке утилитой getopt параметров возникла какая-то ошибка, то её значение будет отличаться от 0. В этом случае можно вывести подсказку по использованию программы и завершить выполнение:
if [ $? != 0 ] ; then echo «Использование: $(basename $0) <-p SFX> <-n><-t>» echo » -s выводить число подходящих файлов» echo » -p использовать суффикс SFX для имён файлов» echo » -t режим тестирования – не выполнять реальных действий» exit 0 fi
На практике часто встречаются скрипты, в которых подобная подсказка заключена в отдельную функцию. Так исходный код лучше воспринимается. Следует отдельно отметить выражение $(basename $0) — оно отделяет имя запущенной программы от полного пути к исполняемому файлу.
После обработки ошибок продолжаем выполнять полезные действия:
Теперь все аргументы отсортированы и готовы к обработке. Производится она обычно с помощью конструкции case, заключённой в цикл. Выглядит это следующим образом:
i=0 for i do case «$i» in -s ) flag_s=1 ; shift ;; -p ) flag_p=1 ; sfx=$2 ; shift 2 ;; -t ) flag_t=1 ; shift ;; esac done
Здесь используется нестандартный синтаксис работы с case. Двойное ; (;;) применяется для завершения последовательности действий для определённого условия. Это выполняет декоративную функцию и упрощает восприятие исходного кода.
Источник
Bash в примерах. Часть вторая.
Еще больше основ программирования в bash
Обработка аргументов
Давайте разберемся как передавать и обрабатывать аргументы скрипта и ознакомимся с основными управляющими конструкциями bash.
В простом скрипте из предыдущей статьи мы использовали переменную «$1«, которая содержит первый аргумент командной строки при вызове скрипта. Аналогично можно использовать «$2», «$3» и так далее для доступа ко второму, третьему… аргументам командной строки. Вот пример:
#!/bin/bash echo «Имя скрипта — $0» echo «Первый аргумент: $1» echo «Второй аргумент: $<2>» echo «Семнадцатый аргумент: $<17>» echo «Количество аргументов: $#»
Обратите внимание, что в переменной «$0» содержится имя самого скрипта, который запущен из командной строки. А переменная «$#» содержит количество переданных скрипту аргументов. Использование фигурных скобок необязательно только для переменных состоящих из одной цифры (с $0 по $9). Попробуйте позапускать этот скрипт с разным числом аргументов и посмотрите как он работает.
Иногда необходимо сослаться сразу на все аргументы командной строки. Для этого в bash есть специальная переменная «$@«, которая содержит все аргументы переданные скрипту разделенные пробелами. Мы будем использовать эту переменную чуть позже при рассказе о циклах со счетчиком (конструкция «for»).
Управляющие конструкции bash
Если вы раньше программировали на процедурных языках, таких как Си, Паскаль, Перл и тому подобных, вам должны быть знакомы управляющие конструкции вроде «if», «for» и другие. В bash тоже есть все эти конструкции. В следующих разделах пособия я познакомлю вас с ними и покажу чем они отличаются от подобных конструкций из других языков программирования. Если вы раньше не программировали — не волнуйтесь. Материал будет изложен подробно и дополнен примерами, так что даже новичок в программировании сможет разобраться.
Оператор условного выбора «if»
Если вы раньше программировали на языке Си, то должны знать сколько требуется усилий чтобы определить какой из двух файлов был создан первым, например. А все из-за того, что в Си нет встроенных средств для такого рода сравнения. Вместо этого приходится использовать системный вызов stat() для каждого файла и затем сравнивать результат вручную. Но в bash есть встроенный механизм сравнения файлов, Поэтому узнать «доступен ли для чтения файл /tmp/myfile» настолько же просто как и узнать «превосходит ли значение переменной ‘myvar’ 4».
Привожу список наиболее часто употребляемых в bash операторов сравнения
Файлы -a file истинно если файл существует. -d file истинно если файл существует и является директорией. -f file истинно если файл существует и является обычным файлом. -r file истинно если файл существует и доступен для чтения. -s file истинно если файл существует и его размер больше 0. -w file истинно если файл существует и доступен для записи. -x file истинно если файл существует и является исполняемым. file1 -nt file2 истинно если файл file1 новее чем file2 или file1 (в соответствии со временем последнего изменения) существует, а file2 нет. file1 -ot file2 истинно если файл file1 старше чем file2 или file2 существует, а file1 нет. file1 -ef file2 истинно если оба файла ссылаются на одно и то же устройство или инод. Строки -z string истинно если строка имеет нулевую длину. -n string истинно если длина строки не нулевая. string1 = string2 истинно если строки равны. string1 != string2 истинно если не равны. string1 истинно если строка 1 стоит в алфавитном порядке перед строкой 2. string1 > string2 истинно если строка 1 стоит в алфавитном порядке после строки 2.
В следующих примерах показано как использовать оператор сравнения в конструкции «if»:
if [ -z «$myvar» ] then echo «Переменная ‘myvar’ не определена.» fi
Квадратные скобки вычисляют условное выражение стоящее в них (это синоним встроенной функции bash — test). Возвращаемый результат — 1 или 0 в зависимости от того выполняется условие или нет. в скобках может стоять несколько выражений, связанных логическими операторами «и» или «или«. Подробнее на странице справки help test.
В некоторых случаях одна и та же операция сравнения может быть сделана несколькими разными способами. Обе конструкции из следующего примера функционально идентичны:
if [ «$myvar» -eq 3 ] then echo «myvar равно 3» fi if [ «$myvar» = «3» ] then echo «myvar равно 3» fi
В первой конструкции из предыдущего примера использована операция арифметического сравнения, а во втором — операция сравнения строк.
Тонкости при сравнении строк
В большинстве случаев, когда вы не заключаете строки и строковые переменные в двойные кавычки, это может привести к ошибке. Почему? Да потому что в строке может встретится пробел или символ табуляции, которые bash не сможет правильно обработать. Вот пример некорректного сравнения строк:
if [ $myvar = «foo bar oni» ] then echo «yes» fi
В этом примере, если значение переменной «$myvar» будет равно «foo», код будет работать как и ожидается и не печатать ничего. Но если значение переменной «$myvar» будет равно «foo bar oni», скрипт вызовет следующую ошибку:
[: too many arguments
После подстановки значения переменной, bash пытается произвести следующую операцию сравнения:
[ foo bar oni = «foo bar oni» ]
В этом случае bash не может правильно обработать сравнение строк содержащих пробелы, одна из которых не заключена в двойные кавычки. Интерпретатор думает, что в квадратных скобках слишком много аргументов. После заключения переменной в двойные кавычки, ошибка не возникает и код работает так как мы задумали. Запомните, если вы возьмете в привычку заключать в двойные кавычки все строковые аргументы и переменные, то избежите множества ошибок подобных описанной выше. Вот исправленный кусок кода:
if [ «$myvar» = «foo bar oni» ] then echo «yes» fi
Этот код будет работать корректно и не преподнесет нам больше никаких неприятных сюрпризов.
Конструкция создания циклов «for»
Хорошо, с условными переходами разобрались, пора перейти к циклическим конструкциям. Начнем с управляющей конструкции «for«. Вот стандартный пример:
#!/bin/bash for x in one two three four do echo «number $x» done Результат: number one number two number three number four
Что же именно произошло? Часть «for x» цикла «for» определяет переменную (называемую итератором) «$x», которая последовательно принимает значения «one», «two», «three», и «four» (по одному за один такт цикла). После присвоения каждого нового значения переменной «$x», выполняется тело цикла (код между словами «do» и «done»). В теле цикла мы выводим на печать значение переменной «$x». Заметим, что после слова «in» в конструкции «for» всегда стоит некий список. В данном примере мы указали четыре слова, но этот список может содержать имена файлов или даже шаблон (wildcard). В следующем примере показано как использовать шаблоны при инициализации итератора цикла:
#!/bin/bash for myfile in /etc/r* do if [ -d «$myfile» ] then echo «$myfile (dir)» else echo «$myfile» fi done результат: /etc/rc0.d (dir) /etc/rc1.d (dir) /etc/rc2.d (dir) /etc/rc3.d (dir) /etc/rc4.d (dir) /etc/rc5.d (dir) /etc/rc6.d (dir) /etc/rc.local /etc/rcS.d (dir) /etc/rearj.cfg /etc/reportbug.conf /etc/resolvconf (dir) /etc/resolv.conf /etc/rmt /etc/rpc /etc/rsyslog.conf /etc/rsyslog.d (dir)
Код этого цикла исполнится для каждого файла из /etc/ имя которого начинается с «r». Сначала bash найдет все такие файлы и заменит шаблон строкой /etc/rc0.d /etc/rc1.d /etc/rc2.d /etc/rc3.d /etc/rc4.d … /etc/rsyslog.d перед тем как приступить к выполнению цикла. В теле цикла для каждого файла из списка проверяется является ли этот файл директорией при помощи оператора «-d«. Если файл оказался директорией, рядом с его называнием печатается «(dir)».
В списке инициализации итератора можно использовать несколько шаблонов одновременно и даже переменные окружения:
for x in /etc/r. /var/lo* /home/drobbins/mystuff/* /tmp/$
Bash в этом примере подставляет значение переменной и раскрывает шаблоны. А затем копирует все файлы в заданную директорию.
До этого все примеры содержали шаблоны основанные на абсолютных путях, но можно использовать и относительные:
for x in ../* mystuff/* do echo «$x is a silly file» done
В этом примере bash раскрывает шаблон относительно текущей рабочей директории (не той в которой находится скрипт, а той которую показывает команда «pwd»). Поиграйтесь с этим скриптом, позапускайте его из разных директорий и посмотрите на результат.
Иногда может потребоваться запустить цикл по списку аргументов из командной строки. Вот как это делается:
В этом примере мы использовали переменную «$@» о которой говорили выше.
Арифметика в shell
Перед тем как приступить к разбору следующего вида циклической конструкции, научимся при помощи интерпретатора производить простые арифметические операции. Просто заключите арифметическое выражение в конструкцию «$(( ))» и bash посчитает ее значение. Вот несколько примеров:
$ echo $(( 100 / 3 )) 33 $ myvar=»56″ $ echo $(( $myvar + 12 )) 68 $ echo $(( $myvar — $myvar )) 0 $ myvar=$(( $myvar + 1 )) $ echo $myvar 57
Теперь, когда вы познакомились с вычислением арифметических выражений в shell, пришло время рассказать о циклических конструкциях «while» и «until».
Циклические конструкции с условиями («while» и «until»)
«while»–цикл исполняется пока выражение в квадратных скобках истинно. Он имеет следующий формат:
while [ условие ] do код done
В следующем примере тело цикла исполняется ровно 10 раз:
myvar=0 while [ $myvar -ne 10 ] do echo «$myvar» myvar=$(( $myvar + 1 )) done
После каждого выполнения кода тела цикла переменная «myvar» увеличивается на 1. Когда значение переменной становится равным 10, условие в квадратных скобках не выполняется и цикл прерывается.
«Until»–цикл очень похож на «while»–цикл: он повторяется пока выражение в квадратных скобках ложно. Вот пример «until»–цикла по функциональности идентичного «while»–циклу из предыдущего примера:
myvar=0 until [ $myvar -eq 10 ] do echo $myvar myvar=$(( $myvar + 1 )) done
Экстренный выход из цикла
Для экстренного выхода из «for», «while» или «until» цикла используется команда break. Для выхода из нескольких вложенных циклов — break N, где N — количество вложенных циклов.
name=0 while : do wget http://example.com/gallery/$
В последнем примере: «while :» — бесконечный цикл. Двоеточие — это команда bash которая не делает ничего но всегда завершается успехом. Переменная $? содержит статус с которым завершилась последняя команда (подробнее о специальных переменных смотри man bash). В нашем случае код отличный от 0 обозначает что при скачивании файла произошла ошибка. Как только условие в квадратных скобках выполнено, интерпретатор переходит к исполнению команды стоящей после логического и (&&). Break прерывает выполнение цикла.
Предпоследнюю строку предыдущего примера можно заменить на знакомую нам условную конструкцию «if» (помним, что в bash одно действие можно сделать несколькими разными способами):
то же самое но через условную конструкцию:
if [ $? -ne 0 ] then break fi
Или в одну строку
if [ $? -ne 0 ]; then break; fi
Да, конструкции можно записывать в одну строку, только нужно поставить несколько разделяющих знаков «точка с запятой». Но не стоит привыкать к такой форме записи — это усложняет читаемость кода.
Команда–переключатель «case»
Конструкция условного перехода «case» может оказаться очень полезной. Вот пример ее использования:
case «$
В этом примере сначала происходит обработка строки в переменной «$x» — «$
Функции и пространство имен
В bash вы можете определять свои функции, как и в других языках программирования (C, Pascal…). Эти функции могут принимать аргументы, используя механизм очень похожий на механизм работы с аргументами командной строки. Вот пример определения простой функции:
tarview() < echo -n "Displaying contents of $1 " if [ $<1##*.>= tar ] then echo «(uncompressed tar)» tar tvf $1 elif [ $ <1##*.>= gz ] then echo «(gzip-compressed tar)» tar tzvf $1 elif [ $ <1##*.>= bz2 ] then echo «(bzip2-compressed tar)» cat $1 | bzip2 -d | tar tvf — fi >
Выше мы определили функцию с именем «tarview», которая принимает один аргумент — имя тарбола. Эта функция определяет вид тарбола (без сжатия, сжатый gzip-ом или bzip2) по расширению, затем печатает этот тип и показывает содержимое архива. Если формат определить не удалось, выводится соответствующее сообщение. Вот пример вызова функции:
$ ./tarview.sh shorten.tar.gz Displaying contents of shorten.tar.gz (gzip-compressed tar) drwxr-xr-x ajr/abbot 0 1999-02-27 16:17 shorten-2.3a/ -rw-r—r— ajr/abbot 1143 1997-09-04 04:06 shorten-2.3a/Makefile -rw-r—r— ajr/abbot 1199 1996-02-04 12:24 shorten-2.3a/INSTALL -rw-r—r— ajr/abbot 839 1996-05-29 00:19 shorten-2.3a/LICENSE .
Как вы видите, обращение к аргументам внутри функции происходит по тем же именам как и к аргументам командной строки внутри скрипта. Переменная «$#» содержит количество переданных функции аргументов. Единственное что остается по-прежнему — переменная «$0«. Она содержит название скрипта при вызове функции из скрипта или строку «bash» при вызове функции напрямую из командной строки.
Вызвать функцию из командной строки можно следующим образом: сохраняем код функции в файл (например с названием «/myfunc.txt») а затем даем следующую команду:
или что тоже самое
Эти команды строка за строкой исполняют инструкции написанные в файле в текущей командной оболочке. (Можно так же напечатать код функции строка за строкой в командной строке, но первый способ намного удобнее). После этого можем вызывать нашу функцию прямо из командной строки:
/.bash_profile, тогда вы сможете вызывать ее из командной строки в любое время при следующем логине.
Пространство имен
Часто возникает потребность создать переменную окружения внутри функции. В большинстве компилируемых языков (например Си), когда вы создаете переменную внутри функции, она попадает в отдельное пространство имен этой функции. Например, если вы напишите функцию «my function» на C и внутри этой функции создадите переменную «x», то она никак не повлияет на переменную с тем же именем «x», созданную вне функции «myfunction».
Но в bash все по-другому. В bash, когда вы создаете переменную внутри функции, она попадает в общее пространство имен. Это значит, что она может перезаписать значение глобальной переменной с таким же именем и продолжит свое существование даже после завершения исполнения функции:
Результатом исполнения этого кода будет строка «ne two three three«, показывающая что переменная «myvar», созданная внутри функции перезаписала значение глобальной переменной «myvar» и что последнее значение итератора «x» равное «three» продолжило существование даже после завершения функции.
В этом простом примере ошибку легко заметить и устранить, переименовав переменные внутри функции. Но есть гораздо более правильное решение этой проблемы: при создании переменной можно явно указать что она является локальной при помощи инструкции «local«. Созданная таким способом внутри функции переменная будет отнесена к локальному пространству имен этой функции и не сможет никак повлиять на глобальную переменную с таким же именем. Следующий пример демонстрирует возможность создания локальной переменной:
Результатом выполнения этого кода будет строка «hello» — значение глобальной переменной «myvar» (на которую никак не повлияла локальная переменная «myvar», созданная внутри функции), а локальная переменная «x» перестает существовать после завершения функции.
Единственное условие при котором вы не должны использовать локальные переменные внутри функций — если хотите изменить значение глобальной переменной.
Подведение итогов
Вот и все. Теперь вы имеете представление о программировании в bash и можете писать свои скрипты. За более подробной информацией обращайтесь к справке man bash или к руководству Advanced Bash-Scripting Guide
Источник