Примеры скриптов на bash

Примеры скриптов на bash

Существует достаточное количество оболочек, например — sh, zsh, ksh и другие. Но мы остановимся на Bash, ведь это самая популярная оболочка среди Linux. Теперь даже Microsoft добавила поддержку Bash.

Эта статья предназначена для тех кто хоть немного знаком с языком сценариев Bash. Давайте рассмотрим некоторые примеры Bash скриптов, которые могут быть полезными в вашей повседневной работе.

Примеры Bash скриптов в Linux

Чтобы посмотреть какой интерпретатор команд у вас используется введите команду:

Как видите у меня установлен именно Bash.

1. Первая программа. Модификация команды ‘rm’

#!/bin/bash
dir="$HOME/.archive/" # directory for deleted files
if [ -d $dir ]; then # check the directory .archive/
file="$1"
null=""
else mkdir $dir | chmod 700 $dir # if there is no, create
fi
if [ $file == $null ]; then # error, if not specified file #
echo -e "/! No file.. Usage: $0 filename 😉 | archive directory — $dir /! "
exit 1
fi
mv $file $dir$(date "+%H.%d.%m").$file # move file to .archive/

Все мы знаем что делает команда rm, она удаляет файлы. Эта программа создает папку

/.archive. Далее проверяет задан ли аргумент. Без аргумента программа выдаст сообщение об ошибке и прекратит работу. Если ей передан путь к файлу, она помещает его в директорию

/.archive и добавляет дату(час,день,месяц) в начало имя файла, чтобы мы могли понять когда удалили файл.

Далее я приведу еще несколько программ, но без обяснений. Эти программы можно модифицировать, улучшать как угодно. Попробуйте написать что-то свое.

2. Проверка наличия пути к программе в переменной PATH

#!/usr/bin/bash
in_path() <
cmd=$1 ourpath=$2 result=1
oldIFS=$IFS IFS=":"
for directory in "$ourpath"
do
if [ -x $directory/$cmd ]; then
result=0
fi
done
IFS=$oldFS
return $result
>
##########
4ck() <
var=$1
if [ "$var" != "" ]; then
if [ "$" = "/" ]; then
if [ ! -x $var ];then
return 1
fi
elif ! in_path $var "$PATH" ; then
return 2
fi
fi
>
##############################
if [ $# -ne 1 ]; then
echo "Usage: $0 command" >&2
exit 0
fi
4ck "$1"
case $? in
0 ) echo "[$1] found in PATH" ;;
1 ) echo "[$1] not found or not executable" ;;
2 ) echo "[$1] not found in PATH" ;;
esac
exit 0
#############################

3. Нормализация вывода даты

#!/bin/bash
monthto() <
case $1 in
1 ) month="Jan" ;; 7 ) month="Jul" ;;
2 ) month="Feb" ;; 8 ) month="Aug" ;;
3 ) month="Mar" ;; 9 ) month="Sep" ;;
4 ) month="Apr" ;; 10 ) month="Oct" ;;
5 ) month="May" ;; 11 ) month="Nov" ;;
6 ) month="Jun" ;; 12 ) month="Dec" ;;
* ) echo "$0: Unknown month value $1" >&2 exit 1
esac
return 0
>
#################
if [ $# -ne 3 ] ; then
echo "Usage: $0 month day year" >&2
echo "Formats are August 3 1962 and 8 3 1962" >&2
exit 1
fi
if [ $3 -le 99 ]; then
echo "$O: expected 4-digit year value." >&2
exit 1
fi
if [ -z $(echo $1|sed ‘s/[[:digit:]]//g’) ]; then
monthto $1
else
month="$(echo $1 | cut -c1 | tr ‘[:lower:]’ ‘[:upper:]’)"
month="$month$(echo $1 | cut -c2-3 | tr ‘[:upper:]’ ‘[:lower:]’)"
fi
echo $month $2 $3
exit 0

4. Создание библиотек сценариев

Библиотеки — это сценарии которые можно включать в другие сценарии.

Такие сценари можно легко включить в другой файл командой source и вызвав нужную вам фунцию.

Заключение

Сегодня мы разобрали несколько примеров Bash скриптов. Узнали как их исползовать в виде библиотечных сценариев. Очень много полезного можно написать на Bash, ограничение тому лишь ваше воображение. Но на самом деле, тема Bash скриптов велика и есть целые книги посвященные этой теме. Надеюсь статья была полезна. Про основы работы с Bash вы можете прочитать здесь.

Оцените статью:

Об авторе

Подсел на Slackware.

5 комментариев

"исползовать" — опечатка, пропущен мягкий знак

Сегодня ничего мы не разобрали.
кроме как узнали что там у нас за интерпретатор а дальше
я просто деранул с нета пару "примеров" но что там я сам не в курсе ребята.

В первом скрипте несколько ошибок и дыр.
1. file и null установлены только если существует директория архива
2. Mkdir | chmod — зачем тут пайп?
3. $dir="$HOME/.archive" . Mkdir $dir — если в $HOME есть пробел или любой другой спецсимвол, то начнутся спецэффекты.
4. if [ $file == $null ]; если в переданном файле спецсимволы, то получим спецэффекты. Кроме того, условие сработает если нет директории архива.
5. mv $file $dir$(date "+%H.%d.%m").$file та же ошибка, те же спецэффекты. И ещё одна проблема: если в течение часа мы "удаляем" два файла с одинаковым именем, то бэкап теряется. Проблема становится ещё более интересной в случае директорий.

Вместо второго скрипта можно использовать which или whereis. (этот и следующий на ошибки не проверял). Фунционал третьего скрипта умеет команда date.

круто. зря прочитал

Ну, с нормализацией даты можно и проще, например так: date ‘+%M:%H %e %B %Y’
Разукрашивающая последовательность вида $[что-то_здесь — работает не навсех андроид-девайсах, посему кроссплатформнее использовать 33[что-то_здесь
В общем-то скрипты для тренировки. А так да, с годами у каждого пользователя Unix-подобных ОС, накапливается порядочное количество скриптов для удобства работы. Я вот, например, всегда забывал, как пересчитывать права файлов в циферки, в rwx и написал тогда это (сейчас уже не использую, т.к. уже запомнилось, что -rwxr-xr-x — это 0755, только из-за редкости использования SUID и SGID ещё путаю):
#!/bin/bash
#
# calcmod
# Calculation of permission
# Author: Serega@Russia
#
############

# Вывод ошибок:
errorka()
<
echo -e "33[31;1mОшибка аргумента!33[0m
"
exit 0
>
#=============#

# Вывод справки:
helpik()
<
echo -en "33[1m" 1>&2
echo -n ‘calcmod’
echo -en "33[0m" 1>&2
echo ‘ [аргумент]’
echo ‘ Примеры:’
echo ‘ calcmod 755’
echo ‘ calcmod 0755’
echo ‘ calcmod rwxr—r—‘
echo ‘ calcmod rwsr—r—‘
echo ‘ calcmod rwSr—r—‘
echo ‘ calcmod rwxr—r-T’
echo ‘ calcmod rwxr—r-t’
echo ‘ calcmod П’
echo ‘ calcmod Г’
echo »
exit 0
>
#==============#

# Расчёт из буквенных значений:
calcmod_letter()
<
(( "$len_arg" != 9 )) && errorka
trio_arg=$(echo "$arg" | sed ‘s/^(. )(. )(. )/1 2 3/’)
i=1
bit=0
rwx=»
for trio in $trio_arg
do
n=0
exp_trio_arg=$(echo "$trio" | sed ‘s/(.)/ 1/g;s/^ //’)
symb=$(echo "$exp_trio_arg" | cut -d ‘ ‘ -f1)
[ -z $(echo "$symb" | grep ‘[r-]’) ] && errorka
[ "$symb" = ‘r’ ] && n=4
symb=$(echo "$exp_trio_arg" | cut -d ‘ ‘ -f2)
[ -z $(echo "$symb" | grep ‘[w-]’) ] && errorka
[ "$symb" = ‘w’ ] && let n=n+2
symb=$(echo "$exp_trio_arg" | cut -d ‘ ‘ -f3)
[ -z $(echo "$symb" | grep ‘[xsS-]’) ] && (( $i != 3 )) && errorka
[ -z $(echo "$symb" | grep ‘[xtT-]’) ] && (( $i == 3 )) && errorka
if [ "$symb" = ‘x’ ]
then let n=n+1
elif [ "$symb" = ‘s’ ]
then
let n=n+1
(( $i == 1 )) && let bit=bit+4
(( $i == 2 )) && let bit=bit+2
elif [ "$symb" = ‘S’ ]
then
(( $i == 1 )) && let bit=bit+4
(( $i == 2 )) && let bit=bit+2
elif [ "$symb" = ‘t’ ]
then
let n=n+1
let bit=bit+1
elif [ "$symb" = ‘T’ ]
then
let bit=bit+1
fi
let i=i+1
rwx=$(echo "$rwx$n")
done
mode="$arg"
print_letter
(( $check_bit != 0 )) && check_calc=1 && bit=’?’
mode="$bit$rwx"
>
#=============================#

Каким бы простым ни был графический интерфейс в Linux и сколько бы там ни было функций, все равно есть задачи, которые удобнее решать через терминал. Во-первых, потому что это быстрее, во-вторых — не на всех машинах есть графический интерфейс, например, на серверах все действия выполняются через терминал, в целях экономии вычислительных ресурсов.

Если вы уже более опытный пользователь, то, наверное, часто выполняете различные задачи через терминал. Часто встречаются задачи, для которых нужно выполнять несколько команд по очереди, например, для обновления системы необходимо сначала выполнить обновление репозиториев, а уже затем скачать новые версии пакетов. Это только пример и таких действий очень много, даже взять резервное копирование и загрузку скопированных файлов на удаленный сервер. Поэтому, чтобы не набирать одни и те же команды несколько раз можно использовать скрипты. В этой статье мы рассмотрим написание скриптов на Bash, рассмотрим основные операторы, а также то как они работают, так сказать, bash скрипты с нуля.

Основы скриптов

Скрипт или как его еще называют — сценарий, это последовательность команд, которые по очереди считывает и выполняет программа-интерпретатор, в нашем случае это программа командной строки — bash.

Читайте также:  Sniper ghost warrior 2 проблемы с текстурами

Скрипт — это обычный текстовый файл, в котором перечислены обычные команды, которые мы привыкли вводить вручную, а также указанна программа, которая будет их выполнять. Загрузчик, который будет выполнять скрипт не умеет работать с переменными окружения, поэтому ему нужно передать точный путь к программе, которую нужно запустить. А дальше он уже передаст ваш скрипт этой программе и начнется выполнение.

Простейший пример скрипта для командной оболочки Bash:

!/bin/bash
echo "Hello world"

Утилита echo выводит строку, переданную ей в параметре на экран. Первая строка особая, она задает программу, которая будет выполнять команды. Вообще говоря, мы можем создать скрипт на любом другом языке программирования и указать нужный интерпретатор, например, на python:

!/usr/bin/env python
print("Hello world")

!/usr/bin/env php
echo "Hello world";

В первом случае мы прямо указали на программу, которая будет выполнять команды, в двух следующих мы не знаем точный адрес программы, поэтому просим утилиту env найти ее по имени и запустить. Такой подход используется во многих скриптах. Но это еще не все. В системе Linux, чтобы система могла выполнить скрипт, нужно установить на файл с ним флаг исполняемый.

Этот флаг ничего не меняет в самом файле, только говорит системе, что это не просто текстовый файл, а программа и ее нужно выполнять, открыть файл, узнать интерпретатор и выполнить. Если интерпретатор не указан, будет по умолчанию использоваться интерпретатор пользователя. Но поскольку не все используют bash, нужно указывать это явно.

chmod ugo+x файл_скрипта

Теперь выполняем нашу небольшую первую программу:

Все работает. Вы уже знаете как написать маленький скрипт, скажем для обновления. Как видите, скрипты содержат те же команды, что и выполняются в терминале, их писать очень просто. Но теперь мы немного усложним задачу. Поскольку скрипт, это программа, ему нужно самому принимать некоторые решения, хранить результаты выполнения команд и выполнять циклы. Все это позволяет делать оболочка Bash. Правда, тут все намного сложнее. Начнем с простого.

Переменные в скриптах

Написание скриптов на Bash редко обходится без сохранения временных данных, а значит создания переменных. Без переменных не обходится ни один язык программирования и наш примитивный язык командной оболочки тоже.

Возможно, вы уже раньше встречались с переменными окружения. Так вот, это те же самые переменные и работают они аналогично.

Например, объявим переменную string:

Значение нашей строки в кавычках. Но на самом деле кавычки не всегда нужны. Здесь сохраняется главный принцип bash — пробел — это специальный символ, разделитель, поэтому если не использовать кавычки world уже будет считаться отдельной командой, по той же причине мы не ставим пробелов перед и после знака равно.

Чтобы вывести значение переменной используется символ $. Например:

Модифицируем наш скрипт:

!/bin/bash
string1="hello "
string2=world
string=$string1$string2
echo $string

Bash не различает типов переменных так, как языки высокого уровня, например, С++, вы можете присвоить переменной как число, так и строку. Одинаково все это будет считаться строкой. Оболочка поддерживает только слияние строк, для этого просто запишите имена переменных подряд:

!/bin/bash
string1="hello "
string2=world
string=$string1$string2 and me
string3=$string1$string2" and me"
echo $string3

Обратите внимание, что как я и говорил, кавычки необязательны если в строке нет спецсимволов. Присмотритесь к обоим способам слияния строк, здесь тоже демонстрируется роль кавычек. Если же вам нужны более сложные способы обработки строк или арифметические операции, это не входит в возможности оболочки, для этого используются обычные утилиты.

Переменные и вывод команд

Переменные не были бы настолько полезны, если бы в них невозможно было записать результат выполнения утилит. Для этого используется такой синтаксис:

$( команда )

С помощью этой конструкции вывод команды будет перенаправлен прямо туда, откуда она была вызвана, а не на экран. Например, утилита date возвращает текущую дату. Эти команды эквивалентны:

Понимаете? Напишем скрипт, где будет выводиться hello world и дата:

string1="hello world "
string2=$(date)

Теперь вы знаете достаточно о переменных, и готовы создать bash скрипт, но это еще далеко не все. Дальше мы рассмотрим параметры и управляющие конструкции. Напомню, что это все обычные команды bash, и вам необязательно сохранять их в файле, можно выполнять сразу же на ходу.

Параметры скрипта

Не всегда можно создать bash скрипт, который не зависит от ввода пользователя. В большинстве случаев нужно спросить у пользователя какое действие предпринять или какой файл использовать. При вызове скрипта мы можем передавать ему параметры. Все эти параметры доступны в виде переменных с именами в виде номеров.

Переменная с именем 1 содержит значение первого параметра, переменная 2, второго и так далее. Этот bash скрипт выведет значение первого параметра:

Управляющие конструкции в скриптах

Создание bash скрипта было бы не настолько полезным без возможности анализировать определенные факторы, и выполнять в ответ на них нужные действия. Это довольно-таки сложная тема, но она очень важна для того, чтобы создать bash скрипт.

В Bash для проверки условий есть команда Синтаксис ее такой:

if команда_условие
then
команда
else
команда
fi

Эта команда проверяет код завершения команды условия, и если 0 (успех) то выполняет команду или несколько команд после слова then, если код завершения 1 выполняется блок else, fi означает завершение блока команд.

Но поскольку нам чаще всего нас интересует не код возврата команды, а сравнение строк и чисел, то была введена команда [[, которая позволяет выполнять различные сравнения и выдавать код возврата зависящий от результата сравнения. Ее синтаксис:

[[ параметр1 оператор параметр2 ]]

Для сравнения используются уже привычные нам операторы ,=,!= и т д. Если выражение верно, команда вернет 0, если нет — 1. Вы можете немного протестировать ее поведение в терминале. Код возврата последней команды хранится в переменной $?:

Теперь объединением все это и получим скрипт с условным выражением:

!/bin/bash
if [[ $1 > 2 ]]
then
echo $1" больше 2"
else
echo $1" меньше 2 или 2"
fi

Конечно, у этой конструкции более мощные возможности, но это слишком сложно чтобы рассматривать их в этой статье. Возможно, я напишу об этом потом. А пока перейдем к циклам.

Циклы в скриптах

Преимущество программ в том, что мы можем в несколько строчек указать какие действия нужно выполнить несколько раз. Например, возможно написание скриптов на bash, которые состоят всего из нескольких строчек, а выполняются часами, анализируя параметры и выполняя нужные действия.

Первым рассмотрим цикл for. Вот его синтаксис:

for переменная in список
do
команда
done

Перебирает весь список, и присваивает по очереди переменной значение из списка, после каждого присваивания выполняет команды, расположенные между do и done.

Например, переберем пять цифр:

for index in 1 2 3 4 5
do
echo $index
done

Или вы можете перечислить все файлы из текущей директории:

for file in $(ls -l); do echo "$file"; done

Как вы понимаете, можно не только выводить имена, но и выполнять нужные действия, это очень полезно когда выполняется создание bash скрипта.

Второй цикл, который мы рассмотрим — это цикл while, он выполняется пока команда условия возвращает код 0, успех. Рассмотрим синтаксис:

while команда условие
do
команда
done

!/bin/bash
index=1
while [[ $index

Как видите, все выполняется, команда let просто выполняет указанную математическую операцию, в нашем случае увеличивает значение переменной на единицу.

Хотелось бы отметить еще кое-что. Такие конструкции, как while, for, if рассчитаны на запись в несколько строк, и если вы попытаетесь их записать в одну строку, то получите ошибку. Но тем не менее это возможно, для этого там, где должен быть перевод строки ставьте точку с запятой ";". Например, предыдущий цикл можно было выполнить в виде одной строки:

index=1; while [[ $index

Все очень просто я пытался не усложнять статью дополнительными терминами и возможностями bash, только самое основное. В некоторых случаях, возможно, вам понадобиться сделать gui для bash скрипта, тогда вы можете использовать такие программы как zenity или kdialog, с помощью них очень удобно выводить сообщения пользователю и даже запрашивать у него информацию.

Выводы

Теперь вы понимаете основы создания скрипта в linux и можете написать нужный вам скрипт, например, для резервного копирования. Я пытался рассматривать bash скрипты с нуля. Поэтому далеко не все аспекты были рассмотрены. Возможно, мы еще вернемся к этой теме в одной из следующих статей.

Читайте также:  Gamdias hephaestus v2 surround sound

Основы программирования в bash

Введение

Вы, должно быть, пока не представляете зачем нужно учиться программированию в bash. Вот несколько причин:

Bash уже есть у вас в системе

Если вы проверите, то скорее всего обнаружите, что bash уже запущен у вас в системе. Даже если вы используете другой shell в качестве командного интерпретатора, bash наверняка установлен, потому что он является стандартной командной оболочкой в линуксе. Так как bash уже запущен, выполнение скриптов написанных на bash-е является эффективным, потому что они разделяют часть оперативной памяти с уже запущенным процессом bash. Да и зачем загружать еще один интерпретатор, если у вас уже есть bash, который справляется со своей работой и делает это хорошо?

Вы уже используете его

Но bash не просто запущен в вашей системе, вы еще ежедневно взаимодействуете с ним. Он всегда рядом, так что есть смысл научиться управляться с ним чтобы полноценно использовать все его возможности. После этого ваше общение с линуксом станет намного веселее и продуктивнее. Но почему вы должны учиться программировать? Все просто: вы уже мыслите в терминах исполнения программ, копирования файлов и перенаправления вывода программ. Не должны ли вы теперь изучить язык, который позволит вам строить из этих простых элементов мощные и экономящие ваше время конструкции с использованием которых вы уже знакомы? Командная оболочка открывает перед вами весь потенциал UNIX. А bash это командная оболочка линукс. Он связывает вас с компьютером. Изучив bash, вы автоматически увеличите свою производительность использования UNIX или Linux — все настолько просто.

Перед началом

Неправильный подход к изучению языка bash может сбить вас с толку. Многие новички вводят команду man bash чтобы прочитать страницу со справкой, которая содержит только краткое техническое описание функционала командной оболочки. Другие вызывают info bash (чтобы посмотреть документацию в формате info), но получают или ту же страницу мануала или немногим более удобный для пользователя материал.

Новички могут быть немного разочарованы, узнав что стандартная справка не может предоставить всей информации и предназначена для пользователей уже знакомых с основами программирования на языке shell. В мануале много замечательно организованной технической информации, но для новичков ее польза невелика.

Эта серия статей поможет вам освоиться в командной строке. В этом пособии описано как использовать основные синтаксические конструкции языка shell для написания своих скриптов. Я постараюсь объяснить все простым языком, чтобы вы не только поняли как это все работает, но и разобрались как это использовать. Прочитав эту серию статей, вы научитесь писать свои собственные скрипты и будете комфортно себя чувствовать в командной строке. После этого вы сможете пополнять свои знания читая (и понимая!) стандартную документацию по bash. Давайте начнем.

Переменные окружения

В bash как и практически во всех остальных командных оболочках пользователь может создавать и определять свои переменные окружения, которые хранятся как текстовые (ASCII) строки. Одно из самых полезных свойств переменных окружения заключается в том, что они являются стандартной частью модели процессов в UNIX. Это значит, что переменные окружения могут использовать не только скрипты командной оболочки, но и компилированные программы. Когда мы экспортируем переменную окружения в bash, любая программа запущенная нами получает к ней доступ. Хорошим примером служит команда vipw, которая позволяет руту редактировать файл с паролями пользователей (/etc/passwd). Установив переменную окружения EDITOR в значение своего любимого текстового редактора, вы можете указать vipw использовать его, а не редактор по умолчанию.

Переменную в bash-е можно определить следующим способом:

$ myvar=’Это моя переменная окружения!’

Эта команда создает переменную с именем «myvar» которая содержит строку «Это моя переменная окружения!». Следует заметить что: Во-первых, рядом со знаком «=» не должно быть пробелов; (попробуйте и вы увидите, что на команду с пробелами интерпретатор выдает ошибку). Во-вторых, если значение нашей переменной содержит пробелы или знаки табуляции, нужно заключить его в кавычки.

В-третьих, обычно можно использовать двойные кавычки вместо одинарных, но именно в этом примере использование двойных кавычек вызовет ошибку интерпретатора, так как значение нашей переменной содержит один из тех специальных символов (о которых сказано в замечании выше) — «!«, но внутри одинарных кавычек никакие специальные символы не работают. Символ «!» в bash отвечает за так называемую «HISTORY EXPANSION» — работу с файлом истории командной строки (подробности см. в мануале). На смотря на то, что функция работы с историей команд при помощи «!» бывает очень полезной, именно сейчас мы хотим видеть его просто как восклицательный знак.

Давайте посмотрим как можно прочитать значение нашей переменной:

$ echo $myvar Это моя переменная окружения!

Ставя перед именем переменной знак $, мы сообщаем интерпретатору, что нужно заменить ее значением. Это называется подстановкой переменной (variable substitution/expansion).

Но что будет, если мы попробуем сделать так:

$ echo foo$myvarbar foo

Мы хотели вывести на экран надпись ‘fooЭто моя переменная окружения!bar‘, но ничего не получилось. Что же произошло? Интерпретатор не смог определить значение какой именно переменной нужно подставить ($m, $my, $myvar, $myvarbar и т.д.) В таких неоднозначных случаях можно явно указать bash на имя переменной:

$ echo foo$bar fooЭто моя переменная окружения!bar

Как вы видите, заключив имя нужной переменной в фигурные скобки, мы явно указали интерпретатору где находится переменная, а где простой текст. Выражение $myvar быстрее напечатать и оно работает в большинстве случаев, но $ будет работать всегда корректно. Оба этих выражения указывают на одну переменную, но вы должны использовать второе (с фигурными скобками), если имя переменной не отделено от окружающего текста пробелами или знаками табуляции.

Вернемся к упомянутой нами возможности экспортировать переменные. Экспортированная переменная автоматически становится доступна для любого скрипта или программы, запущенной после экспортирования. Shell-скрипт может прочитать значение переменной при помощи встроенных в shell средств работы с переменными окружения, а программы на C — используя функцию getenv(). Вот небольшой пример кода на языке C, который вы можете напечатать и скомпилировать. Он поможет взглянуть на переменные окружения со стороны языка C:

#include #include int main(vo ,myenvvar); >

Сохраните этот код в файл myenv.c, а затем скомпилируйте:

$ gcc myenv.c -o myenv

После этого в ващей рабочей директории появится исполняемый файл ‘myenv‘. Запустите его, и он выведет вам значение переменной ‘EDITOR‘ (если оно присвоено). Вот что получилось у меня:

$ ./myenv The editor environment variable is set to (null)

Так как переменная не определена, наша программа не может получить к ней доступ. Давайте создадим эту переменную и присвоим ей какое-нибудь значение:

$ EDITOR=mousepad $ ./myenv The editor environment variable is set to (null)

Так тоже не работает. Мы ожидали что программа напечатает «mousepad», но результат не изменился. Это произошло потому что мы забыли экспортировать переменную ‘EDITOR‘. В этот раз должно сработать:

$ export EDITOR $ ./myenv The editor environment variable is set to mousepad

Итак, мы на примере убедились, что сторонний процесс (в нашем случае программа на C) не может получить доступ к переменной окружения до тех пор пока она не экспортирована. Кроме того, вы можете определить переменную и экспортировать ее одной командой:

Эта команда выполняет то же действие, что и двухшаговая версия (присвоение значения и экспорт). Наступило подходящее время показать как сбросить значение переменной окружения (другими словами — удалить переменную) при помощи ‘unset‘:

$ unset EDITOR $ ./myenv The editor environment variable is set to (null)

Как распарсить строку?

Распарсить строку — значит разделить ее на более короткие составляющие. Это одна из частых операций, встречающихся при написании shell-скриптов. Иногда скрипту нужно определить имя конкретного файла или директории, зная полный (абсолютный) путь к нему. На bash это можно сделать всего одной командой:

$ basename /usr/local/share/doc/foo/foo.txt foo.txt $ basename /usr/home/drobbins drobbins

Читайте также:  Apple time capsule 2tb a1409

basename‘ — очень удобная утилита для расщепления строк на составляющие. Вторая команда — ‘dirname‘ — возвращает другую часть строки (путь к директории где находится файл):

$ dirname /usr/local/share/doc/foo/foo.txt /usr/local/share/doc/foo $ dirname /usr/home/drobbins/ /usr/home

Подстановка команд

Очень полезно знать как присвоить переменной результат выполнения какой-либо команды. Сделать это довольно просто:

$ MYDIR=$(dirname /usr/local/share/doc/foo/foo.txt) $ echo $MYDIR /usr/local/share/doc/foo

То что мы сделали называется подстановка команд. В первой строке примера мы просто заключили команду в конструкцию $( ).

Заметим, что тоже самое можно сделать применив вместо конструкции $( ) обратные кавычки « (клавиша клавиатуры сразу над клавишей Tab):

$ MYDIR=`dirname /usr/local/share/doc/foo/foo.txt` $ echo $MYDIR /usr/local/share/doc/foo

В баше, как мы видим, можно сделать одно действие несколькими разными способами. Используя подстановку команд, мы можем поместить любую команду в обратные кавычки или в конструкцию $( ) и присвоить ее вывод переменной. Очень полезная вещь! Вот пример как использовать подстановку серии команд соединенных через пайп:

$ MYFILES=$(ls -1 /etc | grep %$@

*!G4;:%#`pa) $ echo $MYFILES pam.conf pam.d pango papersize passwd passwd-

Стоит заметить, что использование конструкции $( ) предпочтительней чем обратных кавычек в shell-скриптах, т.к. она более универсальна по отношению к разным командным интерпретаторам, ее легче набирать и читать и ее можно использовать во вложенных конструкциях:

$ MYFILES=$(ls $(dirname foo/bar/oni))

Расщепление строк для профессионалов

basename‘ и ‘dirname‘ замечательные утилиты, но бывают случаи, когда нужно произвести более сложные операции над строками чем манипуляции с путями. Для более эффективной работы со строками можно использовать встроенные средства подстановки значений переменных bash. Ранее мы уже использовали подстановку переменных, которая выглядела так: $. Но в bash есть и встроенные средства манипуляции со строками. Посмотрим на следующий пример:

$ MYVAR=foodforthought.jpg $ echo $ rthought.jpg $ echo $ odforthought.jpg

Что же означает конструкция $ из предыдущего примера? Мы написали внутри $ < >имя переменной, затем два знака хэша (или диеза, кому как привычней) и шаблон («*fo»). Bash взял нашу переменную ‘MYVAR’, нашел наибольшую по длине подстроку строки ‘/foodforthought.jpg’ (начиная от начала строки) которая совпала с шаблоном «*fo» и удалил ее. С первого раза в этих тонкостях сложно разобраться. Для того чтобы понять как работает конструкция ##, давайте рассмотрим пошагово как bash ищет совпадение подстроки с шаблоном. Начинаем поиск подстроки совпадающей с шаблоном «*fo» с начала строки «/foodforthought.jpg». Вот список всех таких подстрок:

f fo совпадает с шаблоном "*fo" foo food foodf foodfo совпадает с шаблоном "*fo" foodfor foodfort foodforth foodfortho foodforthou foodforthoug foodforthought foodforthought.j foodforthought.jp foodforthought.jpg

После проверки всех этих вариантов, найдено две строки попадающие под шаблон. Bash выбирает самую длинную из них, а затем удаляет эту подстроку и возвращает результат.

Вторая форма подстановки переменной показанная в примере отличается от первой только наличием одного знака хэша (#), а не двух. И bash выполняет те же действия, за исключением того, что удаляет не самую длинную а самую короткую из совпавших с шаблоном подстрок. Как видно, после удаления самой короткой подстроки совпавшей с шаблоном (fo) у нас остается строка «/odforthought.jpg».

Это может показаться очень запутанным, поэтому я покажу как можно быстро запомнить эту фичу bash. Когда мы ищем самое длинное совпадение, то используем два хэша (##), т.к. «##» длиннее чем «#». А когда ищем самое короткое совпадение, используем #. Видите, не так уж и сложно! Постойте, а как же запомнить, что поиск начинается от начала строки? Очень просто! Заметим, что в английской раскладке клавиатуры сочетание Shift–4 дает нам знак $ используемый в bash для подстановки значения переменной. Сразу перед знаком $ на клавиатуре находится # (как бы вначале) и таким образом «#» удаляет символы от начала строки. Вы захотите узнать, как удалить последовательность символов от конца строки. Как можно догадаться, это делается при помощи знака (%), находящегося на клавиатуре сразу после «$». Вот небольшой пример удаления окончания строки:

$ MYFOO="/chickensoup.tar.gz" $ echo $ chickensoup $ echo $ chickensoup.tar

Как вы видите, одинарный и двойной знаки процента (% и %%) работают также как «#» и «##», но удаляют подстроку совпавшую с шаблоном от конца строки. Запомните, что можно не использовать знак «*», если вы хотите удалить какое-то конкретное окончание строки.

$ MYFOOD="chickensoup" $ echo $ chicken

В этом примере нет разницы использовать % или %%, т.к. есть только одно совпадение. И не забывайте при выборе «#» или «%» смотреть на 3,4 и 5 клавиши клавиатуры.

Мы можем использовать еще одну форму подстановки значения переменной для выделения подстроки по заданной длине и позиции начала:

$ EXCLAIM=cowabunga $ echo $ cow $ echo $ abunga

Эта форма очень удобна. Просто укажите разделяя двоеточиями позицию начала подстроки — первое число и длину подстроки — второе число.

Применение расщепления строк

Разделению строк научились, давайте теперь напишем небольшой shell-скрипт. Наш скрипт будет принимать один аргумент — имя файла и если этот файл имеет расширение .tar, скрипт будет сообщать что это тарбол. (На самом деле определять тип файла по расширению не совсем корректно. Для этих целей существует команда file. Пример только для демонстрации.) Вот этот скрипт:

#!/bin/bash if [ "$<1##*.>" = "tar" ] then echo "Кажется это тарбол." else echo "На первый взгляд, это не похоже на тарбол." fi

Первая строка обязательно должна присутствовать в каждом скрипте. Она показывает путь к интерпретатору, который будет выполнять скрипт. Ее синтаксис, как видно из примера — «#! ».

Сохраните текст скрипта из примера в файл mytar.sh, затем измените права доступа к нему ‘chmod 755 mytar.sh‘ (это сделает файл исполняемым). И, наконец, запустите скрипт с аргументом в виде имени файла, как показано в следующем примере:

$ ./mytar.sh thisfile.tar Кажется это тарбол. $ ./mytar.sh thatfile.gz На первый взгляд, это не похоже на тарбол.

Хорошо, вроде работает, но не очень функционален. Перед тем как усовершенствовать наш скрипт, рассмотрим конструкцию if, использованную в нем. В квадратных скобках сравниваются две строки («=» — это оператор сравнения в bash). Результат сравнения — булевое выражение ‘false’ или ‘true’ (правда или ложь). Но давайте посмотрим какие именно строки сравниваются. Справа все понятно — строка «tar». Слева стоит разобранное нами выше выражение, удаляющее начало строки в переменной $1 по шаблону «*.» (вся строка до последней точки, т.к. используются два хэша ##). После этой операции подстановки остается только часть строки после последней точки — расширение другими словами. Если в переменной $1 содержится имя файла с расширением «tar», то результатом сравнения строк будет булевое true.

Вам наверное интересно, почему при проверке условия мы использовали переменную «$1». Все очень просто: переменная $1 содержит в себе первый аргумент переданный скрипту ($2 — второй аргумент и так далее). С этой функцией разобрались, рассмотрим теперь подробнее конструкцию условного выбора «if«.

Конструкция if

Как и во многих языках программирования, в bash есть условные конструкции. Они имеют формат, описанный ниже. Будьте внимательны: слова «if» и «then» должны находится на разных строках. Старайтесь выравнивать горизонтально всю конструкцию, включая заключительный «fi» и все «else». Это делает код намного удобнее для чтения и отладки. В дополнении к простой форме «if,else» есть еще несколько других форм условных конструкций:

if [ условие ] then действие fi

В приведенном выше примере ‘действие’ выполняется только если ‘условие’ верно, в противном случае скрипт продолжает выполнение инструкций со строки идущей за «fi».

if [ условие ] then действие elif [ условие_2 ] then действие_2 elif [ условие_3 ] then . . . else действие_x fi

А эта конструкция последовательно проверяет условия и если они верны, то исполняет соответствующее действие. Если ни одно из условий не верно, то выполняется ‘действие_x’ стоящее после ‘else’ (если оно есть). Потом продолжается исполнение команд идущих за этой конструкцией «if,then,else», если таковые есть.

В следующей части

В этой статье мы рассмотрели базовую функциональность bash. Пришло время немного ускориться и начать писать свои собственные shell-скрипты. В следующей части пособия я расскажу о функциях, циклах, пространстве имен и о других важных вещах. После этого мы будем готовы писать относительно сложные скрипты. До встречи!

Ссылка на основную публикацию
Adblock detector