Bash – это мощный инструмент написания сценариев и основа систем Linux. Здесь вы узнаете некоторые основные сведения
Bash-скрипты являются высокоэффективным средством автоматизации задач, особенно тех, которые используют преимущества других существующих программ. Такая автоматизация часто требует повторения аналогичной операции несколько раз, и именно здесь на помощь приходит for loop
Системные администраторы Linux и Mac обычно знакомы с созданием сценариев через терминал, но даже пользователи Windows могут принять участие в работе с помощью подсистемы Windows для Linux
Как работают сценарии Bash
Сценарий bash – это обычный текстовый файл, содержащий ряд команд, которые оболочка bash может прочитать и выполнить.Bash является оболочкой по умолчанию в macOS до Catalina и в большинстве дистрибутивов Linux
Если вы никогда раньше не работали с shell-сценариями, вам следует начать с самого простого случая. Это позволит вам отработать ключевые понятия, включая создание сценария и его выполнение
Сначала создайте следующий файл в удобном месте (в идеале сначала откройте терминал и перейдите в нужную директорию):
#!/bin/bash
echo'Hello, World'
Первая строка сообщает программе, которая ее выполняет, как ее запускать (т.е.с помощью интерпретатора bash). Вторая – это просто команда, как и любая другая, которую вы можете ввести в командной строке. Сохраните этот файл как hello_world.sh , затем:
$ chmod +x hello_world.sh
$./hello_world.sh
Команда chmod в первой строке делает файл исполняемым, что означает, что его можно запустить, набрав его имя, как во второй строке
Если в терминале вы видите, что в строке появились слова ‘Hello, World’, значит, все работает так, как нужно
Как работают циклы For
В общем программировании существует два основных типа цикла for: numeric и foreach. Числовой тип традиционно является наиболее распространенным, но в bash обычно используется наоборот
Числовые циклы for обычно ориентируются на одно целое число, которое определяет, сколько итераций будет выполнено, например:
for(i = 0; i < 100; i++) {
/* statements to execute repeatedly */
Это хорошо знакомый цикл for, который будет повторяться ровно 100 раз, пока i не изменится внутри цикла, или другой оператор не приведет к остановке выполнения цикла for
Циклы Foreach, напротив, обычно работают со структурами, такими как списки или массивы, и выполняют итерации для каждого элемента в этой коллекции:
people = 'Peter''Paul''Mary'
foreach (people as person) {
if(person =='Paul') {
}
В некоторых языках используется немного другой синтаксис, который меняет порядок следования коллекции и элемента:
people = 'Peter''Paul''Mary'
for(personinpeople) {
if(person =='Paul') {
}
For in Loops
В bash более распространен цикл foreach или for in -loop. Основной синтаксис прост:
forargin list
do
/* statements to execute repeatedly */
/* the value of arg can be obtained using$arg*/
done
Например, для итерации по трем файлам с явными именами:
forfileinone.c two.c three.c
do
ls$file
done
Если такие файлы существуют в текущей директории, то результатом работы этого скрипта будет:
one.c
two.c
three.c
Вместо фиксированного набора файлов список можно получить с помощью шаблона glob (включающего подстановочные знаки – специальные символы, обозначающие другие символы). В следующем примере цикл for перебирает все файлы (в текущем каталоге), имена которых заканчиваются на ‘.xml’:
forfilein*.xml
do
ls -l$file
done
Вот несколько примеров вывода:
$ -rw-r--r-- 1 bobby staff 2436 3 Nov 2019 feed.xml
$ -rw-r--r-- 1 bobby staff 6447 27 Oct 16:24 sitemap.xml
Это может выглядеть очень длинным способом:
$ ls -l *.xml
Но есть существенная разница: цикл for выполняет программу ls 2 раза, каждый раз передавая ей одно имя файла. В отдельном примере ls шаблон glob (*.xml) сначала сопоставляет имена файлов, а затем отправляет их все, как отдельные параметры командной строки, одному экземпляру ls
Вот пример, в котором используется программа wc (word count), чтобы сделать разницу более очевидной:
$ wc -l *.xml
44 feed.xml
231 sitemap.xml
275 total
Программа wc подсчитывает количество строк в каждом файле отдельно, а затем выводит общий подсчет по всем файлам. В отличие от этого, если wc работает в цикле for:
forfilein*.xml
do
wc -l$file
done
Вы по-прежнему будете видеть счетчик для каждого файла:
44 feed.xml
231 sitemap.xml
Но общего суммарного итога нет, потому что wc выполняется изолированно, при каждой итерации цикла
Когда список не является списком
Существует очень простая и распространенная ошибка при работе с циклами for, связанная с тем, как bash обрабатывает цитируемые аргументы/строки. Перебор списка файлов должен выполняться следующим образом:
forfileinone.c two.c
Не так:
forfilein'one.c two.c'
Во втором примере имена файлов заключены в двойные кавычки, в результате чего получается список с одним параметром; цикл for будет выполнен только один раз. Этой проблемы можно избежать, используя в таких случаях переменную:
FILES='one.c two.c'
forfilein$FILES
do
done
Обратите внимание, что само объявление переменной должно заключать свое значение в двойные кавычки!
Для без списка
Поскольку перебирать нечего, цикл for работает на тех аргументах командной строки, которые были предоставлены скрипту при вызове. Например, если у вас есть сценарий с именем args.sh , содержащий следующее:
#!/bin/sh
for
do
echo$a
done
Затем выполнение args.sh даст следующее:
$./args.sh one two three
one
two
three
Bash распознает этот случай и рассматривает for a do как эквивалент for a in $@ do , где $@ – специальная переменная, представляющая аргументы командной строки
Эмуляция традиционного числового цикла For
Сценарии Bash часто имеют дело со списками файлов или строками вывода других команд, поэтому цикл типа for in является обычным. Однако традиционная операция в стиле c все еще поддерживается:
for(( i=1; i<=5; i++ ))
do
echo$i
done
Это классическая форма с тремя частями, в которой:
- переменная инициализируется (i=1) при первом появлении цикла.
- цикл продолжается до тех пор, пока условие (i<=5) истинно.
- при каждом прохождении цикла переменная увеличивается (i++).
Итерация между двумя значениями – достаточно частое требование, поэтому существует более короткая и чуть менее запутанная альтернатива:
forin{1. 5}
do
echo$i
done
Расширение скобок, которое имеет место, эффективно преобразует вышеприведенный цикл for в:
forin1 2 3 4
Более тонкое управление контуром с помощью прерывания и продолжения
Более сложные циклы for часто нуждаются в способе досрочного выхода или немедленного перезапуска основного цикла со следующим по очереди значением. Для этого bash заимствует операторы break и continue, распространенные в других языках программирования. Вот пример, который использует оба этих оператора для поиска первого файла длиной более 100 символов:
#!/bin/bash
forfilein
do
if ! -f$file
then
echo$fileis not a file'
continue
fi
num_chars=$(wc -c <$file
echo$fileis$num_charscharacters long'
if$num_chars-gt 100
then
echo'Found$file
break
fi
done
Цикл for здесь работает со всеми файлами в текущем каталоге. Если файл не является обычным файлом (напр.если это каталог), оператор continue используется для перезапуска цикла со следующим по очереди файлом. Если это обычный файл, второй условный блок определит, содержит ли он более 100 символов. Если да, то оператор break используется для немедленного выхода из цикла for (и достижения конца сценария)
Заключение
Сценарий bash – это файл, содержащий набор инструкций, которые могут быть выполнены. Цикл for позволяет повторять часть сценария много раз. С помощью переменных, внешних команд, а также операторов break и continue сценарии bash могут применять более сложную логику и выполнять широкий спектр задач
Комментировать