Операторы сравнения:
Примеры:
Операторы проверки файлов
Возвращается true в случае, если:
- -e файл существует;
- -a файл существует. Эффект идентичен использованию -e. Опция является «устаревшей»,
использование нежелательно;
- -f обычный файл (не директория и не файл-устройство);
- -s файл ненулевого размера;
- -d файл является директорией;
- -b файл является блочным устройством;
- -c файл является символьным устройством;
device0="/dev/sda2" # / (корневой каталог)
if [ -b "$device0" ]
then
echo "$device0 - блочное устройство."
fi
# /dev/sda2 - блочное устройство.
device1="/dev/ttyS1" # PCMCIA-модем.
if [ -c "$device1" ]
then
echo "$device1 - символьное устройство."
fi
# /dev/ttyS1 - символьное устройство.
- -p файл является каналом (pipe);
- -h файл является символической ссылкой;
- -L файл является символической ссылкой;
- -S файл является сокетом;
- -t файл (дескриптор) ассоциирован с терминальным устройством. Эта опция может быть
использована для проверки stdin [ -t 0 ] или stdout [ -t 1 ] в данном скрипте является терминалом;
- -r имеется право на чтение файла (для пользователя вызвавшего проверку);
- -w имеется право на запись файла (для пользователя вызвавшего проверку);
- -x имеется право на исполнение файла (для пользователя вызвавшего проверку);
- -g флаг set-group-id (sgid) установлен для директории или файла. Если для директории установлен
флаг sgid, то файл, созданный внутри неё, унаследует группу, которой принадлежит сама
директория (необязательно группу пользователя, создавшего файл). Это может быть полезно для
каталогов, предназначенных для групповой работы;
- -u флаг set-user-id (suid) установлен для файла. Бинарный файл принадлежащий root-у и имеющий
установленный флаг set-user-id запускается с привилегиями root-а, даже если был вызван обычным
пользователем. Флаг полезен для исполняемых файлов (например, pppd или cdrecord), которым
необходим доступ к оборудованию системы. В случае отсутствия бита suid, эти файлы не смогут
работать от имени обычного пользователя,=.
-rwsr-xr-t 1 root
178236 Oct 2 2000 /usr/sbin/pppd
У файла с установленным флагом suid отображается символ s в списке прав;
- -k установлен sticky bit (липкий бит). Обычно известный как sticky bit, флаг save-text-mode
представляет собой специальный тип прав. Если у файла установлен данный флаг, то этот файл
будет закэширован в памяти для более быстрого доступа к нему. При установке этого бита на
директорию производится ограничение прав на запись. В списке файлов и каталогов sticky bit
отображается в поле прав в виде буквы t.
drwxrwxrwt 7 root
1024 May 19 21:26 tmp/
Пользователь, не являющийся владельцем директории с установленным sticky bit, но имеющий права
на запись в данный каталог, может удалять из него только те файлы, владельцем которых он является.
Это помогает избежать случайного удаления или перезаписи других файлов в папке с общим доступом,
такой как /tmp. (Владелец директории или root, несомненно, могут переименовывать и удалять файлы в ней);
- -O Вы являетесь владельцем файла;
- -G group-id файла совпадает с Вашим ;
- -N файл изменён со времени последнего чтения:
-
f1 -nt f2
файл f1 новее файла f2;
-
f1 -ot f2
файл f1 старше файла f2;
-
f1 -ef f2
файлы f1 и f2 являются жёсткими ссылками на один и тот же файл.
- ! «not» (отрицание) -- инвертирует смысл вышеуказанных проверок (возвращает "истину" в случае отсутствия условий).
Сравнение целочисленных значений:
- -eq значения равны, if [ "$a" -eq "$b" ];
- -ne значения не равны, if [ "$a" -ne "$b" ];
- -gt первое значение больше второго, if [ "$a" -gt "$b" ];
- -ge первое значение больше или равно второму, if [ "$a" -ge "$b" ];
- -lt первое значение меньше второго, if [ "$a" -lt "$b" ];
- -le первое значение меньше или равно второму, if [ "$a" -le "$b" ];
- < первое значение меньше второго (внутри двойных курглых скобок), (("$a" < "$b"));
- <= первое значение меньше или равно второму (внутри двойных круглых скобок), (("$a" <= "$b"));
- > первое значение больше второго (внутри двойных круглых скобок), (("$a" > "$b"));
- >= первое значение больше или равно второму (внутри двойных круглых скобок), (("$a" >= "$b"));
Сравнение строк:
Примеры:
Проверка ссылок на корректность
#!/bin/bash
# broken-link.sh
# Безупречный shell-скрипт, предназначенный для поиска "мертвых" символических
# ссылок и вывода их имён в кавычках. Кавычки необходимы для того, чтобы
# можно было скормить ссылки команде xargs, которая сама с ними разберётся:
# sh broken-link.sh /somedir /someotherdir | xargs rm
#
# Это, однако, лучший метод:
#
# find "somedir" -type l -print0 |\
# xargs -r0 file |\
# grep "broken symbolic" |\
# sed -e 's/^\|: *broken symbolic.*$/"/g'
#
# но это не чистый Bash; мы это исправим.
# Предупреждение: опасайтесь файловой системы /proc и любых циклических ссылок!
# ----------------------------------------------------------
# Если не было передано ни одного параметра, то директорией поиска считается текущая директория.
# В ином случае пути для поиска передаются с помощью аргументов.
[ $# -eq 0 ] && directorys=`pwd` || directorys=$@
# Устанавливается функция linkchk проверяющая переданный ей с помощью
# аргумента каталог на наличие символических ссылок на несуществующие файлы
# и выводящая имена этих ссылок в кавычках.
# Если элемент директории - поддиректория, то он передается
# функции linkchk для обработки.
linkchk ()
{
for element in $1/*; do
[ -h "$element" -a ! -e "$element" ] && echo \"$element\"
[ -d "$element" ] && linkchk $element
# Конечно же, опция '-h' используется для проверки является ли файл ссылкой,
а '-d' - является ли файл директорией.
done
}
# Каждый полученный аргумент, который является корректной директорией, отправляется на
# обработку функции linkchk(). Если аргумент - не директория, то выводится сообщение об ошибке и
# информация по использованию скрипта.
for directory in $directorys
do
if [ -d $directory ]
then
linkchk $directory
else
echo "$directory is not a directory"
echo "Usage: $0 dir1 dir2 ..."
fi
done
exit $?
Арифметические и строковые сравнения
#!/bin/bash
a=4
b=5
# Здесь переменные "a" и "b" могут быть рассмотрены либо как целые числа, либо как строки.
# Так как в Bash переменные не имеют четкого типа, есть различия между
# арифметическим и строковым сравнением.
# Bash разрешает производить арифметические операции и сравнения для переменных,
# значения которых целиком состоят из числовых символов.
echo
if [ "$a" -ne "$b" ]
then
echo "$a не равно $b"
echo "(арифметическое сравнение)"
fi
echo
if [ "$a" != "$b" ]
then
echo "$a не равно $b."
echo "(строковое сравнение)"
# "4" != "5"
# ASCII 52 != ASCII 53
fi
# В данном частном случае оба варианта ( "-ne" и "!=" ) работают.
echo
exit 0
Проверка пустых (null) строк
#!/bin/bash
# str-test.sh: Проверка пустых и незаключенных в кавычки строк
# Исползование if [ ... ]
# Если строка не была проинициализирована, то она не имеет определённого значения.
# Такое состояние называют "null" (это не то же самое, что ноль!).
# string1 не была объявлена или инициализирована
if [ -n $string1 ]
then
echo "Строка \"string1\" не пустая."
else
echo "Строка \"string1\" пустая."
fi
# Получаем НЕверный результат.
# Проверка показывает, что $string1 не пустая, хотя и не была инициализирована.
# ----------------------------------------------------------
# Давайте попробуем еще раз.
# На этот раз $string1 помещена в кавычки.
if [ -n "$string1" ]
then
echo "Строка \"string1\" не пустая."
else
echo "Строка \"string1\" пустая."
fi
# Заключайте строки в кавычки при использовании внутри квадратных скобок !
# ----------------------------------------------------------
# Теперь $string1 осталась "голой".
if [ $string1 ]
then
echo "Строка \"string1\" не пустая."
else
echo "Строка \"string1\" пустая."
fi
# Сработало хорошо
# Оператор проверки [ ... ] без ключей и других операторов может определить пустую строку.
# Но, несомненно, хорошим тоном является всё-таки заключение в кавычки(if [ "$string1" ]).
# if [ $string1 ] имеет один аргумент: "]"
# if [ "$string1" ] имеет два аргумента: пустую переменную "$string1" и "]"
# ----------------------------------------------------------
string1=initialized
# И снова $string1 остаётся без кавычек.
if [ $string1 ]
then
echo "Строка \"string1\" не пустая."
else
echo "Строка \"string1\" пустая."
fi
# Вновь получаем верный результат
# Но до сих пор предпочтительнее использовать кавычки ("$string1"), потому что . . .
# ----------------------------------------------------------
string1="a = b"
# Опять $string1 без кавычек.
if [ $string1 ]
then
echo "Строка \"string1\" не пустая."
else
echo "Строка \"string1\" пустая."
fi
# Не заключённая в кавычки переменная "$string1" явилась причиной неверного результата!
exit 0
zmore
#!/bin/bash
# zmore
# Просмотр сжатых gzip файлов с использованием фильтра 'more'.
E_NOARGS=65
E_NOTFOUND=66
E_NOTGZIP=67
if [ $# -eq 0 ]
# Такой же эффект, как от: if [ -z "$1" ]
# $1 может существовать, но быть пустым: zmore "" arg2 arg3
then
echo "Использование: `basename $0` имя_файла" >&2
# Сообщение об ошибке направляем в stderr.
exit $E_NOARGS
# Скрипт возвращает значение 65 (код ошибки).
fi
filename=$1
if [ ! -f "$filename" ]
# Заключение в кавычки переменной $filename разрешает использование пробелов в ее содержимом.
then
echo "Файл $filename не найден!" >&2
# Сообщение об ошибке направляем в stderr.
exit $E_NOTFOUND
fi
if [ ${filename##*.} != "gz" ]
# Используем фигурные скобки для подстановки.
then
echo "Файл $1 не является архивом gzip!"
exit $E_NOTGZIP
fi
zcat $1 | more
# Используем фильтр 'more'.
# При желании, можно использовать 'less'.
exit $?
# Скрипт возвращает код завершения канала.
# На самом деле команда "exit $?" вовсе необязательна, так как скрипт в любом случае
# вернёт код завершения последней выполненной команды.
Fileinfo: обработка списка файлов, содержащегося в переменной
#!/bin/bash
# fileinfo.sh
# Список интересующих нас файлов.
# В список добавлен фиктивный файл /usr/bin/fakefile.
FILES="/usr/sbin/accept
/usr/sbin/pwck
/usr/sbin/chroot
/usr/bin/fakefile
/sbin/badblocks
/sbin/ypbind"
echo
for file in $FILES
do
# Проверка существования файла.
if [ ! -e "$file" ]
then
echo "$file не существует."; echo
continue
# Переход к следующей итерации.
fi
# Печать 2 полей.
ls -l $file | awk '{ print $8 " размер файла: " $5 }'
whatis `basename $file`
# Информация о файле.
# Заметим, что нужно создать индекс базы данных для whatis для того,
чтобы предыдущая команда работала.
# Чтобы сделать это, из-под пользователя root запустите /usr/bin/makewhatis.
# (Для Debian/Ubuntu используйте команду /usr/bin/mandb - примеч. перев.)
echo
done
exit 0
Обработка списка файлов в цикле for
#!/bin/bash
# list-glob.sh: Создание списка файлов в цикле for с использованием
# "глоббинга".
echo
for file in *
# ^ Bash выполняет раскрытие имён файлов
# в выражениях, которые являются результатом глоббинга.
do
ls -l "$file"
# Отсортированный список всех файлов в $PWD (текущем каталоге).
# Напоминаю, что символу "*" соответствует любое имя файла,
# однако, в для глоббинга имеется исключение - имена файлов, начинающиеся с точки.
# Такие файлы по умолчанию не отображаются в списке совпадающих с шаблоном имен файлов.
# Если шаблону не соответствует ни один файл, то за имя файла принимается сам шаблон.
# Чтобы избежать этого, используйте ключ nullglob
# (shopt -s nullglob).
done
echo
echo
for file in [jx]*
do
rm -f $file
# Удаление файлов, начинающихся с "j" или "x" в $PWD.
echo "Удален файл \"$file\"".
done
echo
exit 0
grep для бинарных файлов
#!/bin/bash
# bin-grep.sh: Вывод строк, содержащих указанную подстроку в бинарном файле.
# Замена "grep" для бинарных файлов.
# Аналогична команде "grep -a"
E_BADARGS=65
E_NOFILE=66
if [ $# -ne 2 ]
then
echo "Использование: `basename $0` искомая_строка имя_файла"
exit $E_BADARGS
fi
if [ ! -f "$2" ]
then
echo "Файл \"$2\" не существует."
exit $E_NOFILE
fi
IFS=$'\012'
# В строке 23 раньше, было: IFS="\n"
for word in $( strings "$2" | grep "$1" )
# Команда "strings" возвращает список строк в двоичных файлах.
# Который затем передается по конвейеру команде "grep" для выполнения поиска.
do
echo $word
done
# (30 строка)
# строки 23 - 30 могут быть заменены более простым
# strings "$2" | grep "$1" | tr -s "$IFS" '[\n*]'
exit 0
Список всех пользователей системы
#!/bin/bash
# userlist.sh
PASSWORD_FILE=/etc/passwd
# Число пользователей
n=1
for name in $( awk 'BEGIN{FS=":"}{print $1}' < "$PASSWORD_FILE" )
# Разделитель полей = : ^^^^^
# Вывод первого поля ^^^^^^^
# Данные берутся из файла паролей ^^^^^^^^^^^^^
do
echo "Пользователь #$n = $name"
let "n += 1"
done
# Пользователь #1 = root
# Пользователь #2 = bin
# Пользователь #3 = daemon
# ...
# Пользователь #30 = bozo
exit 0
Список символических ссылок в каталоге
#!/bin/bash
# symlinks.sh: Список символических ссылок в каталоге.
directory=${1-`pwd`}
# По умолчанию в текущем каталоге, если не определен иной.
# Эквивалентен блоку кода, данному ниже.
# ----------------------------------------------------------
# # Ожидается один аргумент командной строки.
# ARGS=1
#
# # Если каталог поиска не задан...
# if [ $# -ne "$ARGS" ]
# then
# directory=`pwd`
# # текущий каталог
# else
# directory=$1
# fi
# ----------------------------------------------------------
echo "symbolic links in directory \"$directory\""
for file in "$( find $directory -type l )"
# -type l = символические ссылки
do
echo "$file"
done | sort
# sort иначе получится неотсортированный список.
# Строго говоря, в действительности цикл не нужен здесь,
# так как каждая выводимая командой "find" строка раскрывается в одиночное слово.
# Тем не менее, этот способ легко понять и проиллюстрировать.
# Как отмечает Доминик 'Aeneas' Шнитцер,
# в случае отсутствия кавычек для $( find $directory -type l )
# сценарий перестанет выполняться, как только встретится файл, содержащий пробел в имени.
# Сценарий "подавится" именами файлов, содержащими пробел.
exit 0
# альтернатива:
echo "symbolic links in directory \"$directory\""
# Сохранить текущее значение IFS в другой переменной. Никогда не помешает быть чуточку осмотрительным.
OLDIFS=$IFS
IFS=:
for file in $(find $directory -type l -printf "%p$IFS")
do
echo "$file"
done | sort
# можно изменить альтернативу таким образом:
OLDIFS=$IFS
# Пустое значение IFS означает, что нет разрыва между словами
IFS=''
for file in $( find $directory -type l )
do
echo $file
done | sort
# Это работает в "патологическом" случае - если имя каталога содержит двоеточие.
# "Это также исправляет патологический случай имени каталога, содержащего
# двоеточие (или пробел в примере выше)."
Использование команды efax в пакетном режиме
#!/bin/bash
# Отправка факса (пакет 'efax' должен быть установлен).
EXPECTED_ARGS=2
E_BADARGS=85
# Порт может быть другим на вашей машине. Порт по умолчанию PCMCIA-модема.
MODEM_PORT="/dev/ttyS2"
# Проверка необходимого количества аргументов командной строки.
if [ $# -ne $EXPECTED_ARGS ]
then
echo "Использование: `basename $0` телефон# текстовый файл"
exit $E_BADARGS
fi
if [ ! -f "$2" ]
then
echo "Файл $2 не является текстовым файлом."
# Не обычный (regular) файл, либо файл не существует.
exit $E_BADARGS
fi
# Создать fax-файлы из текстовых файлов
fax make $2
for file in $(ls $2.0*)
# Соединять конвертированные файлы.
# используется шаблон ("глоббинг" имен файлов)
# в списке.
do
fil="$fil $file"
done
# Отправить.
efax -d "$MODEM_PORT" -t "T$1" $fil
# Попробуйте добавить опцию "-o1", если команда выше завершилась неудачно.
# Можно обойтись без цикла for-loop с помощью
# efax -d /dev/ttyS2 -o1 -t "T$1" $2.0*
# но это не так поучительно [;-)].
exit $?
# efax также отправляет диагностические сообщения на стандартный вывод (stdout).
Простой цикл while
#!/bin/bash
var0=0
LIMIT=10
while [ "$var0" -lt "$LIMIT" ]
# Пробелы, так как используются квадратные скобки - аналог команды test . . .
do
echo -n "$var0 "
# -n подавляет перевод строки. Пробел, чтобы разделить выводимые числа.
var0=`expr $var0 + 1`
# var0=$(($var0+1)) также допустимо.
# var0=$((var0 + 1)) также допустимо.
# let "var0 += 1" также допустимо.
done
echo
exit 0
Другой пример цикла while
#!/bin/bash
echo
while [ "$var1" != "end" ]
# Эквивалентна команде: while test "$var1" != "end"
do
echo "Введите значение переменной #1 (end - для выхода) "
read var1
echo "Значение переменной #1 = $var1"
# кавычки обязательны, потому что имеется символ "#". . . .
# Если введено слово 'end', то оно тоже выводится на экран,
# потому, что проверка переменной выполняется в начале итерации (перед вводом).
echo
done
exit 0
Результат работы break и continue в цикле
#!/bin/bash
# Верхний предел
LIMIT=19
echo
echo "Печать чисел 1 до 20 (исключая 3 и 11)."
a=0
while [ $a -le "$LIMIT" ]
do
a=$(($a+1))
if [ "$a" -eq 3 ] || [ "$a" -eq 11 ] # Исключить 3 и 11
then
continue
# Пропустить оставшиеся команды и перейти в начало цикла.
fi
echo -n "$a "
# Эта строка не выполнится для 3 и 11.
done
echo
echo
# ----------------------------------------------------------
# Тот же цикл, только 'continue' заменено на 'break'.
a=0
while [ "$a" -le "$LIMIT" ]
do
a=$(($a+1))
if [ "$a" -gt 2 ]
then
break
# Завершение работы цикла.
fi
echo -n "$a "
done
echo
echo
echo
exit 0
Реальный пример использования команды continue N
# Допустим, есть большое количество задач, обрабатывающих некоторые данные,
# которые хранятся в файлах с именами, задаваемыми по шаблону,
# в заданном каталоге.
# Есть несколько машин, которым открыт доступ к этому каталогу
# и я хочу распределить обработку информации между машинами.
# Тогда я для каждой машины обычно пишу нечто подобное:
while true
do
for n in .iso.*
do
[ "$n" = ".iso.opts" ] && continue
beta=${n#.iso.}
#удаление подстроки ".iso" (см. гл. 9.2) - прим. перев.)
[ -r .Iso.$beta ] && continue
[ -r .lock.$beta ] && sleep 10 && continue
lockfile -r0 .lock.$beta || continue
echo -n "$beta: " `date`
run-isotherm $beta
date
ls -alF .Iso.$beta
[ -r .Iso.$beta ] && rm -f .lock.$beta
continue 2
done
break
done
Тонкости использования, в особенности sleep N, индивидуальны для
каждого конкретного приложения, но основной шаблон выглядит так:
while true
do
for job in {pattern}
do
{задача, уже выполненная или выполняемая} && continue
{отметить задачу как запущенную, выполнить
задачу, отметить задачу как выполненную}
continue 2
done
break
# Или что-то наподобие `sleep 600', если нужно избежать завершения цикла.
done
# Этот сценарий завершит работу после того как все данные будут обработаны
# (включая данные, которые поступили во время обработки). Использование
# соответствующих lock-файлов позволяет выполнять обработку на нескольких машинах
# одновременно, не производя дублирующих вычислений [которые, в моем случае,
# выполняются в течении нескольких часов, так что я реально хочу избежать этого].
# Кроме того, поскольку поиск необработанных файлов всегда начинается с
# самого начала, можно задавать приоритеты в именах файлов. Конечно, мы могли бы
# обойтись и без `continue 2', но тогда придется ввести дополнительную
# проверку -- действительно ли была выполнена или нет та или иная задача,
# так, чтобы мы немедленно перейти к поиску следующего необработанного файла.
# (В этом случае мы завершим или приостановим текущую задачу на долгое время для того, чтобы чтобы
# перейти к поиску следующего необработанного файла).
Использование case
#!/bin/bash
# Проверка диапазонов символов.
echo
echo "Нажмите клавишу и затем нажмите Return (Enter)."
read Keypress
case "$Keypress" in
[[:lower:]] ) echo "Буква в нижнем регистре";;
[[:upper:]] ) echo "Буква в верхнем регистре";;
[0-9] ) echo "Цифра";;
* )
echo "Знак пунктуации, пробел или что-то другое";;
esac
# Допускаются диапазоны символов в [квадратных скобках]
# или POSIX-диапазоны в [[двойных квадратных скобках]].
# В первой версии этого примера,
# проверка для символов в верхнем или нижнем регистре учитывала только символы
# [a-z] и [A-Z].
# Это вообще не работает для определенных локалей и/или дистрибутивов Linux.
# Классы символов POSIX (см. BRE - Basic Regular Expressions - прим. перев.) более переносимы.
exit 0
Создание меню, используя case
#!/bin/bash
# Грубый аналог базы данных адресов
# Очистить экран.
clear
echo " Список контактов"
echo " ------- ----"
echo "Выберите одну из следующих персон:"
echo
echo "[E]vans, Roland"
echo "[J]ones, Mildred"
echo "[S]mith, Julie"
echo "[Z]ane, Morris"
echo
read person
case "$person" in
# Обратите внимание: переменная взята в кавычки.
"E" | "e" )
# Допускается ввод символа как в верхнем, так и в нижнем регистре.
echo
echo "Roland Evans"
echo "4321 Flash Dr."
echo "Hardscrabble, CO 80753"
echo "(303) 734-9874"
echo "(303) 734-9892 (факс)"
echo "revans@zzy.net"
echo "Партнер по бизнесу и старый друг"
;;
# Обратите внимание: блок кода, выводящийся после выбора символа, завершается двумя символами "точка с запятой".
"J" | "j" )
echo
echo "Mildred Jones"
echo "249 E. 7th St., Apt. 19"
echo "New York, NY 10009"
echo "(212) 533-2814"
echo "(212) 533-9972 (факс)"
echo "milliej@loisaida.com"
echo "Экс-подруга"
echo "День рождения: 11 февраля"
;;
# Информация о Smith и Zane будет добавлена позднее.
* )
# Выбор по умолчанию.
# Пустой ввод (после нажатия RETURN (ENTER)) тоже обрабатывается здесь.
echo
echo "Таких данных в базе нет."
;;
esac
echo
exit 0
Использование подстановки команды для генерирования значения переменной для case
#!/bin/bash
# case-cmd.sh: Использование подстановки команды для генерирования значения переменной для case.
case $( arch ) in
# Команда "arch" возвращает тип архитектуры.
# Эквивалентна команде 'uname -m' ...
# (На некоторых системах (например Ubuntu 7.10 и выше)
# команда arch может отсутствовать, прим. перев.)
i386 ) echo "Машина на базе процессора 80386";;
i486 ) echo "Машина на базе процессора 80486";;
i586 ) echo "Машина на базе процессора Pentium";;
i686 ) echo "Машина на базе процессора Pentium 2 или выше";;
* ) echo "Другой тип процессора";;
esac
exit 0
Простое сравнение строк
#!/bin/bash
# match-string.sh: Простое сравнение строк.
# Точное сравнение строк.
match_string ()
{
MATCH=0
E_NOMATCH=90
PARAMS=2
# Функция требует два аргумента.
E_BAD_PARAMS=91
[ $# -eq $PARAMS ] || return $E_BAD_PARAMS
case "$1" in
"$2" ) return $MATCH;;
* ) return $E_NOMATCH;;
esac
}
a=one
b=two
c=three
d=two
match_string $a
echo $?
# Неверное количество параметров.
# 91
match_string $a $b
echo $?
# Нет совпадения
# 90
match_string $b $d
echo $?
# Совпадение
# 0
exit 0
Создание меню, используя select
#!/bin/bash
PS3='Выберите ваш любимый овощ: '
# Строка приглашения.
# Иначе по умолчанию берется #? .
echo
select vegetable in "бобы" "морковь" "картофель" "лук" "брюква"
do
echo
echo "Ваш любимый овощ: $vegetable."
echo "Какая гадость!"
echo
break
done
exit 0
Создание меню, используя selectв функции
#!/bin/bash
PS3='Выберите ваш любимый овощ: '
echo
choice_of()
{
select vegetable
# Если [in list] не задан, то 'select' использует аргументы, переданные функции.
do
echo
echo "Ваш любимый овощ - $vegetable."
echo "Фу, какая гадость!"
echo
break
done
}
choice_of бобы рис морковь редиска помидор шпинат
# $1 $2 $3 $4 $5 $6
# передано в функцию choice_of()
exit 0