Передача аргументов
Чтобы передать любое количество аргументов функции bash, просто поместите их сразу после имени функции, разделяя каждую пробелом.
Соблюдайте основные рекомендации при передаче параметров:
•
Переданные параметры $1, $2, $3 … $n, соответствуют номеру параметра по порядку, заданными после имени функции.
•
Переменная $0 зарезервирована для имени функции.
•
Переменная $# содержит общее количество аргументов, переданных функции.
•
Переменная $* или $@ содержит все параметры, переданные функции.
Пример передачи аргументов:
#!/bin/bash greeting () { echo "Привет, $1"
} greeting "Алиса"
Результатом выполнения этого кода будет строка:
Привет, Алиса
79
Теперь у вас есть некоторые знания для того, чтобы правильно писать функции bash.
Примеры
Функция таймер, которая считает сколько прошло времени: timer() { local t; t=$(date '+%s'); test $# -gt 0 && let t-=$1; echo "$t"; } t=$(timer) t=$(timer $t) echo "time used = $t secs"
Код возврата
Код возврата (англ. Exit status) программы, — это целочисленное значение, которое дочерний процесс возвращает родительскому процессу в момент завершения.
При выполнении компьютерных программ операционная система создаёт сущность, называемую процессом, с помощью которой она отслеживает и ведёт учёт выполнения программы. В многозадачных операционных системах, таких как Unix или Linux, новый процесс может быть порождён существующим процессом.
Процесс-создатель называется
«родительским», а создаваемый процесс — «дочерним». После создания дочерний процесс выполняется параллельно с родительским. Такая техника порождения дочерних процессов используется, чтобы передать часть работы дочернему процессу, в ситуациях, когда родительскому процессу не обязательно тратить на неё время. Когда дочерний процесс завершает своё выполнение, он автоматически либо явно по указанию программиста совершает системный вызов exit, передавая ему целое число. В результате вызова exit целое число передаётся родительскому процессу, который может получить его с помощью системного вызова wait.
Команда exit в Bash и коды выхода
Часто при написании сценариев Bash вам необходимо завершить сценарий при выполнении определенного условия или выполнить действие на основе кода выхода команды.
Статус выхода
Каждая команда оболочки возвращает код выхода, когда она завершается успешно или безуспешно.
По соглашению нулевой код выхода указывает, что команда завершилась успешно, а ненулевое значение означает, что произошла ошибка.
80
Специальная переменная $? возвращает статус выхода последней выполненной команды: date &> /dev/null echo $?
Команда date завершена успешно, код выхода равен нулю:
0
Если вы попытаетесь запустить ls в несуществующем каталоге, код выхода будет отличным от нуля: ls /nonexisting_dir &> /dev/null echo $?
2
Код состояния можно использовать для выяснения причины сбоя команды. На странице руководства каждой команды содержится информация о кодах выхода.
При выполнении многокомандного конвейера статус выхода конвейера соответствует состоянию последней команды: sudo tcpdump -n -l | tee file.out echo $?
В приведенном выше примере echo $? напечатает код выхода команды tee.
Команда exit
Команда exit закрывает оболочку со статусом N Он имеет следующий синтаксис: exit N
Если N не задано, код состояния выхода — это код последней выполненной команды.
При использовании в сценариях оболочки значение, указанное в качестве аргумента команды exit возвращается оболочке как код выхода.
Примеры Статус выхода команд
может использоваться в условных командах, таких как if . В следующем примере grep завершит работу с нулем (что означает истину в сценариях оболочки), если «строка поиска» найдена в filename : if grep -q "search-string" filename then echo "String found." else echo "String not found."
81 fi
При запуске списка команд, разделенных && (И) или || (ИЛИ), статус выхода команды определяет, будет ли выполнена следующая команда в списке. Здесь команда mkdir будет выполнена, только если cd вернет ноль: cd /opt/code && mkdir project
Если сценарий завершается exit без указания параметра, код выхода из сценария — это код последней команды, выполненной в сценарии.
/script.sh
#!/bin/bash echo "doing stuff..." exit
Использование только exit — это то же самое, что и exit $? или пропуская exit .
Вот пример, показывающий, как завершить сценарий, если он запущен пользователем без полномочий root:
#!/bin/bash if [[ "$(whoami)" != root ]]; then echo "Only user root can run this script." exit 1 fi echo "doing stuff..." exit 0
Если вы запустите сценарий как root, код выхода будет нулевым. В противном случае скрипт выйдет со статусом 1.
Выводы
Каждая команда оболочки возвращает код выхода при завершении.
Команда exit используется для выхода из оболочки с заданным статусом.
82
16. Regexp и их использование для синтаксического анализа. Полезные утилиты. Регулярные выражения Регулярные выражения (regular expressions) — это текстовый шаблон, который соответствует какому-то тексту. И всё? Да, это всё, для чего они нужны.
Что можно делать с помощью регулярных выражений:
Проверять то, что вводит пользователь, чтобы быть уверенным в правильности данных (например, правильно ли пользователь ввёл e-mail или ip-адрес).
Разбирать большой текст на меленькие кусочки (например, выбирать данные из большого лога).
Делать замены по шаблону (например, убирать непечатаемые символы из XML).
Большинство современных языков программирования и текстовых редакторов поддерживают регулярные выражения. Поддержим их и мы.
/Быть или не быть/ugi ¶
Синтаксис регулярных выражений прост и логичен. Он разделяется на символ-разделитель (он идёт в начале и конце выражения, обычно это /), шаблон поиска и необязательные модификаторы.
Формальный синтаксис такой: [разделитель][шаблон][разделитель][модификаторы]
Разделителем может быть любой символ, но обычно это / или . Важно лишь то, чтобы шаблон начинался и заканчивался одним и тем же разделителем. В самом конце регулярных выражений идут модификаторы, которые нужны, чтобы менять логику работы шаблонов (например, делать регистронезависимый поиск).
Давайте разберём выражение /Быть или не быть/ugi:
/ - начальный символ-разделитель
Быть или не быть - шаблон поиска
/ - конечный символ-разделитель ugi - модификаторы (UTF-8, global, case insensitive)
Данное регулярное выражение будет искать текст. «Быть или не быть» не зависимо от регистра по всему тексту неограниченное количество раз.
Модификатор u нужен для того, чтобы явно указать, что
текст у нас в юникоде, то есть содержит символы, отличные от латиницы. Модификатор i включает
83 регистронезависимый поиск. Модификатор g указывает поисковику идти до победного конца, иначе он остановится после первого удачного совпадения.
"Петя любит Дашу".replace(/Дашу|Машу|Сашу/, "Катю")ю
Не трудно догадаться, что результатом работы js-выражения выше будет текст "Петя любит Катю". Даже, если Петя неровно дышит к Маше или Саше, то результат всё равно не изменится.
Регулярные выражения в LINUX
Интересным вопросом в Linux системах, является управление регулярными выражениями. Это полезный и необходимый навык не только профессионалам своего дела, системным администраторам, но, а также и обычным пользователям линуксоподобных операционных систем. В данной модуле постараемся раскрыть, как создавать регулярные выражения и как их применять на практике в каких-либо целях. Основной областью применение регулярных выражений является поиск информации и файлов в линуксоподобных операционных системах.
Для работы в основном используются следующие символы:
•
"\text" - слова начинающиеся с text
•
"text/" - слова, заканчивающиеся на text
•
"^" - начало строки
•
"$" - конец строки
•
"a-z" - диапазон от a до z
•
"[^t]" - не буква t
•
"\[" - воспринять символ [ буквально
•
"." - любой символ
•
"a|z" - а или z
Регулярные выражения в основном используются со следующими командами:
grep - утилита поиска по выражению
• egrep - расширенный grep
• fgrep - быстрый grep
• rgrep - рекурсивный grep
• sed - потоковый текстовый редактор.
А особенно с утилитой grep. Данная утилита используется для сортировки результатов чего либо, передавая ей результаты по конвейеру. Эта утилита осуществляет поиск и передачу на стандартный вывод результат его. ЕЕ можно запускать с различными ключами, но можно использовать ее другие варианты, которые представлены выше.
84
И есть еще потоковый текстовый редактор. Это не полноценный текстовый редактор, он просто получает информацию построчно и обрабатывает. После чего выводит на стандартный вывод. Он не изменяет текстовый вывод или текстовый поток, он просто редактирует перед тем как вывести его для нас на экран.
Начнем со следующего. Создадим один пустой файл file1.txt, через команду touch. Создадим в текстовом редакторе в той же директории файл file.txt.
Как мы видим в файле file.txt просто набор слов.
Далее мы с помощью данных слов посмотрим, как работают команды.
Первая команда - GREP man grep
Получаем справку по данной команде. Как можно понять из справки команда grep и ее производные — это печать линий совпадающих шаблонов.
Проще говоря, команда grep помогает сортировать те данные, что мы даем команде, через знак конвейера на ввод. Причем в мануале мы можем видеть egrep, fgrep и т.д. данные команды мы можем не использовать. Использовать можно только grep с ключами различными, т. е. ключи просто заменяют эти команды. Можно на примере посмотреть, как работает данная команда.
Например, grep oo file.txt
85
На картинке видно, что команда из указанного файла выбрала по определенному шаблону "oo". Причем даже делает красным цветом подсветку. Можно добавить еще ключик -n, тогда данная команда еще и выведет номер строки, в которой находится то, что ищется по шаблону. Это полезно, когда работаем с каким-нибудь кодом или сценарием. Когда необходимо, что-то найти. Сразу видим, где находится объект поиска или что- то ищем по логам.
При использовании шаблона очень важно понимать, что команда grep, чувствительна к регистрам в шаблонах. Это означает, что Boo и boo это разные шаблоны. В одном случае команда найдет слово, а в другом нет. Можно команде сказать, чтобы она не учитывала регистр. Это делается с помощью ключа -i.
Посмотрим содержимое нашего каталога командой ls, а затем отфильтруем только то, что заканчивается на "ile".
Посмотрим содержимое нашего каталога командой ls
Получается следующее, когда мы даем на ввод команде grep шаблон и где искать, он работает с файлом, а когда мы даем команду ls она выводи содержимое каталога и мы это содержимое передаем по конвейеру на команду grep с заданным шаблоном. Соответственно grep фильтрует переданное содержимое согласно шаблону и выводит на экран. Получается, что команде grep дали, то команда и обработала.
86
Наглядно можно посмотреть на рисунке выше. Мы просматриваем командой cat содержимое файла и подаем на ввод команде grep с фильтрацией по шаблону.
Давайте найдем файлы, в которых содержится сочетание "ple". grep ple file.txt в данном случае команда нашла оба слова содержащие шаблон. Давайте найдем слово, которое будет начинаться с "ple". Команда будет выглядеть следующим образом: grep ^ple file.txt. Значок "^" указывает на начало строки.
Противоположная задача найти слова, заканчивающиеся на "ple". Команда будет выглядеть следующим образом grep ple$ file.txt. Т.е. применять к концу строки, говорит значок "$" в шаблоне.
Можно дать команду grep .o file.txt. В данном выражении знак "." , заменяет любую букву.
Как вы видите вывод шаблона ".ple" вывел только одно слово т.к только слово couple удовлетворяло шаблону , т.к перед "ple" должен был содержаться еще один символ любой.
Попробуем рассмотреть другую команду egrep.
87
Egrep (extended grep) man egrep - отошлет к справке по grep.
Данная команда позволяет использовать более расширенный набор шаблонов. Рассмотрим следующий пример команды: egrep '^(b|d)' file.txt
Шаблон заключается в одинарные кавычки, для
того чтобы экранировать символы, и команда egrep поняла, что это относится к ней и воспринимала выражение как шаблон. Сам же шаблон означает, что поиск будет искать слова, в начале строки (знак ^), содержащие букву b или d.
Мы видим, что команда вернула слова, начинающиеся с буквы b или d.
Рассмотрим другой вариант использования команды egrep. Например: egrep '^[a-k]' file.txt
Получим все слова, начинающиеся с "a" по "к". Знак "[]" - диапазона. Как мы видим слова, начинающиеся с большой буквы, не попали. Все эти регулярные выражения очень пригодятся, когда мы что-то ищем в файлах логах.
Усложним еще шаблон. Возьмем следующий: egrep '^[a-k]|[A-K]' file.txt
Усложняя выражение, мы добавили диапазон заглавных букв сказав команде grep искать диапазон маленьких или диапазон больших букв с начала строки.
88
Вот теперь все хорошо. Слова с Заглавными буквами тоже отобразились.
Как вариант egrep можно запускать просто grep с ключиком -e.
Про fgrep
man fgrep - отошлет к справке по grep. Команда fgrep не понимает регулярных выражений вообще.
Получается следующим образом если мы вводим: egrep c$ file.txt. То команда согласно шаблону, ищет в файле букву "c" в конце слова. В случае же с командой fgrep c$ file.txt, команда будет искать именно сочетание "с$". Т. е. команда fgrep воспринимает символы регулярных выражений, как обычные символы, которые ей нужно найти, как аргументы.
Рекурсивный rgrep
Создадим каталог mkdir folder . Создадим файл great.txt в созданной директории folder со словом Hello при помощью команды echo "Hello" folder/great.txt
И если мы скажем grep Hello * , поищи слово Hello в текущей директории.
Получится следующая картина.
89
Как мы видим, grep не может искать в папках. Для таких случаев и используется утилита rgrep. rgrep Hello *
Дает следующую картину.
Совершенно спокойно в папке найдено было то, что подходило под шаблон.
Данная утилита пробежалась по всем папкам и файлам в них и нашла подходящее под шаблон слово. Т. е. если нам необходимо провести поиск по всем файлам и папкам, то необходимо использовать утилиту rgrep.
Команда sed
man sed - стрим редактор. Т. е. потоковый редактор для фильтрации и редактирования потока данных.
Например, sed -e ‘s/oo/aa’ file.txt - открыть редактор sed и заменить вывод всех oo на aa в файле file.txt. Нужно понимать, что в результате данной команды изменения в файле не произойдут. Просто данные из файла будут взяты и с изменениями выведены на стандартный вывод, т.е. экран. Для
90 сохранения результатов мы можем сказать, чтобы вывел в новый файл указав направление вывода. sed -e ‘s/oo/aa’ file.txt newfile.txt
В данном редакторе мы можем ему сказать использовать регулярные выражения, для этого необходимо добавить ключ -r. У данного редактора очень большой функционал.
17. Разбор скриптов и написание своих скриптов. Linter. Shell check. В простейшем случае шелл скрипт (shell script) — это не что иное, как простая последовательность команд системы, записанная в простой текстовый файл. Создание скриптов поможет сохранить ваше время и силы, которые тратятся на ввод последовательности
команд всякий раз, когда необходимо их выполнить.
Написание shell-скриптов — занятие увлекательное. Скрипты командной строки помогают автоматизировать повседневные дела. Можно создать нечто прекрасное (или не очень), однако, если уж что-то писать, хорошо бы точно знать, что код получается именно таким, каким он нужен программисту. Скрипт, написанный некачественно, может представлять опасность. Большинство новичков пишут скрипты, копируя фрагменты кода со
StackOverflow, находя то, что им нужно, в Google, или пользуясь сайтами с вопросами и ответами по Linux. Такой подход к программированию
91 выливается в некачественный код и в появление ошибок. Вот, например, команда rm, выполнение которой приведёт к катастрофе, так как переменная VAR не определена:
rm -rf
"/
$VAR
/*"
Командная строка и те невообразимые вещи, которые с ее помощью можно творить, — визитная карточка UNIX и всех ее наследников. А где есть командная строка, там есть скрипты. Мы рассмотрим наиболее полезные из них, те, что ты сможешь применять ежедневно для решения самого разного круга задач, начиная от сводки погоды и веб-сервера в одну строку и заканчивая ботом для твиттера в десять строк и скриптом для автоматического запуска любого торрент-клиента.
Для решения многих задач консоль и скрипты годятся гораздо лучше графического интерфейса и поэтому пренебрегать ими никак нельзя. Тем более что любая DE позволяет создать для скрипта иконку, так что для его запуска даже не надо будет открывать консоль.
Простые примеры Итак, сразу перейдем к примерам:
$ curl ifconfig co
Эта простая команда покажет тебе внешний IP — идеальный вариант, если в Сеть ты ходишь через роутер. Все, что она делает, — просто обращается к серверу ifconfig.co, который возвращает обратно IP-шник одной строкой вместо полноценной веб-страницы.
И да, это вовсе не скрипт, это просто команда, но,
чтобы превратить команду в скрипт, достаточно поместить ее в текстовый файл и первой строкой добавить так называемый шебанг, то есть символы #!, за которыми следует имя командного интерпретатора:
#!/bin/bash curl ifconfig co
Далее скрипт сохраняем в каталог /bin и назначаем права на исполнение:
$ chmod
+
x
/bin/
myip sh
Теперь его можно вызывать из командной строки командой myip.sh.
Идем дальше.
92
#!/bin/sh curl
-
4
wttr in
/
Moscow
Этот скрипт позволяет получить сводку погоды на четыре дня. Принцип тут такой же, как в случае с ifconfig.co.
#!/bin/sh dig
+
short txt $1
wp dg cx
А так можно получить краткое описание чего-либо в Википедии, причем с помощью DNS-запроса вместо обращения к веб-серверу. Кстати, веб-сервер через командную строку тоже очень легко создать:
#!/bin/sh while
(
nc
- l
80
<
file html
>
:
)
;
do
:
;
done
Данный скрипт основан на утилите netcat (nc), которую называют швейцарским армейским ножом для сетевых операций. Скрипт запускает цикл, выполняющий команду nc, которая слушает 80-й порт и в ответ на запрос отдает file.html, отправляя переданный запрос в никуда (символ означает noop, то есть пустую операцию).
С помощью простых скриптов и команд можно запросто слушать интернет-радио:
#!/bin/sh mpv
-- volume
=
50
- playlist
/
16bit fm_128
m3u
93
Естественно, плей-лист в формате M3U необходимо заранее скачать с сайта радиостанции. Кстати, если запустить MPlayer с аргументом
--input-ipc-server=/tmp/mpvsocket, им можно будет управлять, записывая команды в файл. Например, настроить громкость: echo
'volume +10'
|
socat
-
/tmp/
mpvsocket
Создай два скрипта: один для запуска, другой для остановки радио (со строкой killall mpv), повесь их на рабочий стол и настрой горячие клавиши DE на управление воспроизведением. Вуаля, у тебя готов плеер для интернет- радио, запустить который можно, просто кликнув по иконке на рабочем столе.
И он почти не будет расходовать память или занимать трей.
Но отвлечемся от сетевых операций и вернемся к локальным делам.
#!/bin/sh tar
- czf
"../${PWD##*/}.tar.gz"
Это один из моих любимых скриптов. Он создает архив tar.gz текущего каталога. Особого внимания здесь заслуживает конструкция ${PWD##*/}, которая берет полный путь до текущего каталога (переменная $PWD) и удаляет из него первую часть вплоть до последнего слеша, оставляя, таким образом, только имя самого каталога. Далее к нему добавляется расширение tar.gz. Более подробно о таких конструкциях ты можешь прочитать в man bash.
#!/bin/sh while true
;
do inotifywait
- r
- e MODIFY
КАТАЛОГ
&&
ТВОЯ
_
КОМАНДА
done
А это уже скрипт, который запускает команду в ответ на изменение файлов в каталоге. Ее можно использовать для множества разных целей, например для автоматического включения плеера при сохранении MP3- файла. Или просто выводить уведомление на десктоп, используя в качестве команды notify-send: notify
- send
"Файл изменен"