Bash by example / Bash в примерах: Part 2: More bash programming fundamentals
| Английский оригинал | Перевод на русский | |
|---|---|---|
Сожалеем, но текст оригинала доступен только зарегистрированным пользователям. |
Вы можете видеть, как использование арифметического вырожения в конечном итоге приводит к тому, что условие оказывается ложным, и цикл завершается. Daemon786 03.02.11 в 15:01 |
|
|
Оператор "until" предоставляет обратную функциональность оператору "while". Он выполняется до тех пор, пока условие ложно. Здесь цикл "until" выполняет те же функции, как и предыдущий цикл "while": Daemon786 03.02.11 в 15:13 |
||
|
myvar=0 Daemon786 21.01.11 в 08:07 |
||
|
Оператор "case" Daemon786 21.01.11 в 09:36 |
||
|
Оператор "case" еще одна удобная условная конструкция. Вот фрагмент примера: Daemon786 03.02.11 в 15:19 |
||
|
case "${x##*.}" in Daemon786 21.01.11 в 08:08 |
||
|
В приведенном примере, bash сначала раскрывает "${x##*.}". В коде "$x" -- это имя файла, а "${x##*.}" удаляет весь текст за исключением того, что следует за последней точкой в имени файла. Затем bash сравнивает получившуюся строку с переменными, перечисленными слева от ")". В данном случае "${x##*.}" сравнивается с "gz", далее с "bz2" и, наконец, с "*". Если "${x##*.}" соответствует какой-нибудь из этих строк или шаблонов, то код, следующий непосредственно за ")", будет выполняться до ";;", после чего bash продолжит выполнять программу после завершающего слова "esac". Если ни шаблоны, ни строки не совпадают, то ни одной строки кода не выполняется, однако в данном фрагменте, по крайней мере, один блок кода будет выполнен, потому что шаблон "*" будет ловить всё, что не соответствует "gz" и "bz2". Daemon786 03.02.11 в 15:28 |
||
|
Функции и пространства имен Daemon786 21.01.11 в 09:36 |
||
|
В bash вы можете даже определять функции подобные тем, что есть в других процедурных языках программирования, таких как Pascal и C. В bash функции могут даже принимать аргументы с помощью системы, очень похожей на способ сценариев принимать аргументы командной строки. Давайте взглянем на пример определения функции: Daemon786 04.02.11 в 14:21 |
||
|
tarview() { Daemon786 21.01.11 в 08:09 |
||
|
Примечание: Daemon786 04.02.11 в 14:42 |
||
|
Выше мы определяем функцию с названием "tarview", которая принимает в качестве аргумента один какой-либо архив. Когда она выполняется, то определяет, какой тип архива был передан в виде аргумента (любой несжатый, сжатый gzip или сжатый bzip), печатает однострочное информационное сообщение, а затем отображает содержимое архива. Ниже указано как должна вызываться даннуя функция (из сценария или из командной строки, после того как она была напечатана или вставлена): Daemon786 04.02.11 в 15:23 |
+1 | |
|
$ tarview shorten.tar.gz Daemon786 04.02.11 в 17:08 |
||
|
Как вы можете видеть, внутри функции можно ссылаться на аргументы, используя тот же механизм, который используется для ссылки на аргументы командной строки. Кроме того, "$#" будет содержать в себе количество аргументов. Единственное, что может работать не так, как ожидалось, это переменная "$0", которая будет раскрыта как строка "bash" (если вы запустили функцию из оболочки интерактивно) или как имя сценария, в котором вызвана функция. Daemon786 09.02.11 в 09:50 |
||
|
Примечание: Daemon786 06.02.11 в 11:36 |
||
|
Пространство имен Daemon786 21.01.11 в 09:36 |
||
|
Часто вам необходимо создать переменную окружения внутри функции. Если возможно, то запомните эту техническую особенность. В большинстве компилируемых языков программирования (таких как C), когда вы создаете переменную внутри функции, она будет расположена в отдельном локальном пространстве имен. Таким образом, если вы определите функцию в C с названием myfunction и в ней определите переменную с именем "x", то любая глобальная (за пределами функции) переменная с именем "x" не будет зависеть от нее, что устранит побочный эффект. Daemon786 06.02.11 в 12:32 |
||
|
Несмотря на то, что это верно в C, в bash это не так. В bash всякий раз, когда вы создаете переменную окружения внутри функции, она добавляется в глобальное пространство имен. Это означает, что она может перезаписать любую глобальную переменную вне функции и будет продолжать существовать даже после завершения работы функции: Daemon786 06.02.11 в 15:22 |
||
|
#!/usr/bin/env bash Daemon786 21.01.11 в 08:09 |
||
|
Когда этот сценарий запустится, он выведет "one two three three", показывая, как определенная в функции "$myvar" затерла глобальную переменную "$myvar", и как переменная контроля цикла "$x" продолжила существовать даже после завершения работы функции (и также затерла бы глобальную "$x", если та была определена). Daemon786 06.02.11 в 16:09 Когда этот сценарий запустится, он выведет "one two three three", показывая, как определенная в функции "$myvar" затерла глобальную переменную "$myvar", и как переменная контроля цикла "$x" продолжила существовать даже после завершения работы функции (и также затерла бы глобальную "$x", если та была определена). Daemon786 06.02.11 в 16:09 |
||
|
В этом простом примере ошибку легко обнаружить и компенсировать с помощью альтернативных имен переменных. Однако это неправильный подход, лучший способ решения этой проблемы, предотвратить возможность перезаписи глобальных переменных, в первую очередь, с помощью команды "local". когда мы используем "local", чтобы создать переменные внутри функции, они будут храниться в локальном пространстве имен и не затрут какие-либо глобальные переменные. Вот как можно реализовать приведенный ниже код, чтобы никакие глобальные переменные не были перезаписаны: Daemon786 06.02.11 в 16:31 |
||
|
#!/usr/bin/env bash Daemon786 21.01.11 в 08:10 |
||
|
Эта функция будет выводить "hello" -- глобальная переменная "$myvar" не была перезаписана, и "$x" не продолжает существовать вне myfunc. В первой строке функции мы создаем локальную переменную x, которую используем позднее, в то время как, во втором случае (local myvar="one two three") мы создаем локальную переменную myvar и присваиваем ей значение. Первая форма удобна для хранения локальных переменных контроля цикла, так как недопустимо писать "for local x in $myvar". Данная функция не перезапишет никаких глобальных переменных, и вам рекомендуется разрабатывать таким образом все ваши функции. Вы не должны использовать "local" только в тех случаях, когда явно хотите изменить глобальную переменную. Daemon786 06.02.11 в 17:13 |
||
|
В заключение Daemon786 21.01.11 в 09:39 |
||
|
Теперь, когда мы рассмотрели наиболее существенные возможности bash, пришло время посмотреть, как создать целую программу на bash. В моей следующей статье мы будем делать именно это. До встречи! Daemon786 06.02.11 в 12:02 |
||
|
Ресурсы Daemon786 21.01.11 в 09:34 |
||
|
Полезные ссылки Daemon786 21.01.11 в 09:35 |
||
|
Дэниэль Роббинс Daemon786 21.01.11 в 09:35 |
