
- •Содержание
- •Часть 1. Введение
- •Глава 1. Зачем необходимо знание языка Shell?
- •Глава 2. Для начала о Sha-Bang
- •Часть 2. Основы
- •Глава 3. Служебные символы
- •Глава 4. Переменные и параметры. Введение.
- •Глава 5. Кавычки
- •Глава 6. Завершение и код завершения
- •Глава 7. Проверка условий
- •Глава 8. Операции и смежные темы
- •Часть 3. Углубленный материал
- •Глава 9. К вопросу о переменных
- •Глава 10. Циклы и ветвления
- •Глава 11. Внутренние команды
- •Глава 12. Внешние команды, программы и утилиты
- •Глава 13. Команды системного администрирования
- •Глава 14. Подстановка команд
- •Глава 15. Арифметические подстановки
- •Глава 16. Перенаправление ввода/вывода
- •Глава 17. Встроенные документы
- •Часть 4. Материал повышенной сложности
- •Глава 18. Регулярные выражения
- •Глава 19. Подоболочки, или Subshells
- •Глава 20. Ограниченный режим командной оболочки
- •Глава 21. Подстановка процессов
- •Глава 22. Функции
- •Глава 23. Псевдонимы
- •Глава 24. Списки команд
- •Глава 25. Массивы
- •Глава 26. Файлы
- •Глава 27. /dev и /proc
- •Глава 28. /dev/zero и /dev/null
- •Глава 29. Отладка сценариев
- •Глава 30. Необязательные параметры (ключи)
- •Глава 31. Широко распространенные ошибки
- •Глава 32. Стиль программирования
- •Глава 33. Разное
- •Глава 34. Bash, версия 2
- •Глава 35. Замечания и дополнения
- •Библиография
- •Приложение B. Справочная информация
- •Приложение D. Коды завершения, имеющие предопределенный смысл
- •Приложение F. Системные каталоги
- •Приложение G. Локализация
- •Приложение H. История команд
- •Приложение I. Пример файла .bashrc
- •Приложение J. Преобразование пакетных (*.bat) файлов DOS в сценарии командной оболочки
- •Приложение K. Упражнения
- •Приложение L. Хронология
- •Приложение M. Авторские права

#+ и неинициализированными элементами.
# В то время как шаблоны /#/ и /%/ совпадают с пустыми и не совпадают #+ с неинициализированными элементами.
echo ${sparseZ[@]//*/$(_GenFunc)} exit 0
Приложение B. Справочная информация
В нижеследующем справочнике представлена информация, касающаяся отдельных моментов написания сценариев на языке командной оболочки Bash.
Таблица B-1. Переменные специального назначения
Переменная
Описание
$0 |
Имя файла сценария |
$1 |
Позиционный параметр #1 (аргумент сценария или функции) |
$2 - $9 |
Позиционные параметры #2 - #9 |
${10} |
Позиционный параметр #10 |
$# |
Количество позиционных параметров |
"$*" |
Все позиционные параметры (как одно слово) * |
"$@" |
Все позиционные параметры (в виде отдельных строк) |
${#*} |
Количество позиционных параметров, переданых из командной строки |
${#@} |
Количество позиционных параметров, переданых из командной строки |
$? |
Возвращаемое значение |
$$ |
Идентификатор процесса -- Process ID (PID) сценария |
$- |
Флаги, переданные сценарию (командой set) |
$_ |
Последний аргумент предыдущей команды |
$! |
Идентификатор последнего фонового процесса (PID) |
* Необходимо заключать в кавычки, в противном случае будет работать как "$@".
Таблица B-2. Операции проверки: Двухместные операции |
|
||
Оператор |
Значение |
---- Оператор |
Значение |
|
|
- |
|
Арифметическое |
|
Сравнение |
|
сравнение |
|
строк |
|
-eq |
Равно |
= |
Равно |
|
|
== |
Равно |
-ne |
Не равно |
!= |
Не равно |
-lt |
Меньше |
\< |
Меньше (в кодах |
|
|
|
ASCII) * |
-le |
Меньше или равно |
|
|
413

-gt |
Больше |
-ge |
Больше или равно |
\> |
Больше (в кодах |
|
ASCII) * |
-z |
Пустая строка |
-n |
Не пустая строка |
Арифметическое |
В двойных круглых скобках (( |
сравнение |
... )) |
> |
Больше |
>= |
Больше или равно |
< |
Меньше |
<= |
Меньше или равно |
* При использовании двойных квадратных скобок [[ ... ]] , необходимо использовать экранирующий символ \ .
Таблица B-3. Операции проверки: Файлы
Оператор Что проверяется
-e |
Файл существует |
-f |
Обычный файл |
-d |
Файл является каталогом |
-h |
Файл является символической ссылкой |
-L |
Файл является символической ссылкой |
-b |
Файл блочного устройства |
-c |
Файл символного устройства |
-p |
Файл является каналом (pipe) |
-S |
Файл является сокетом (socket) |
-t |
Файл связан с терминальным устройством |
-N |
Файл был модифицирован с момента |
|
последнего чтения |
-O |
Вы являетесь владельцем файла |
-G |
Вы принадлежите к той же группе, что и |
|
файл |
-- Оператор Что проверяется
--
-
-s
-r
-w -x
-g
-u -k
F1 -nt F2
F1 -ot F2
F1 -ef F2
Файл не нулевой длины
Файл доступен для чтения
Файл доступен для записи
Файл доступен для
исполнения
Установлен флаг sgid
Установлен флаг suid
Установлен бит "sticky"
Файл F1 более новый, чем F2
*
Файл F1 более старый, чем
F2 *
Файлы F1 и F2 являются
жесткими ссылками на один и тот же файл *
!"NOT" (логическое отрицание (инверсия) результатов всех вышеприведенных проверок)
*Двухместный оператор (требует наличия двух операндов).
414

Таблица B-4. Подстановка параметров и экспансия
Выражение
Описание
${var} |
Значение переменной var, то же, что и $var |
${var-DEFAULT} Если переменная var не инициализирована, то результатом вычисления выражения является $DEFAULT *
${var:-DEFAULT}
${var=DEFAULT}
Если переменная var не инициализирована или пуста, то результатом вычисления выражения является $DEFAULT *
Если переменная var не инициализирована, то результатом вычисления выражения является $DEFAULT *
${var:=DEFAULT}
${var+OTHER}
Если переменная var не инициализирована, то результатом вычисления выражения является $DEFAULT *
Если переменная var инициализирована, то результатом вычисления выражения является $OTHER, иначе -- пустая строка
${var:+OTHER}
${var?ERR_MSG} ${var:?ERR_MSG}
${!varprefix*} ${!varprefix@}
Если переменная var инициализированаset, то результатом вычисления выражения является $OTHER, иначе -- пустая строка
Если переменная var не инициализирована, то выводится $ERR_MSG * Если переменная var не инициализирована, то выводится $ERR_MSG *
Соответствует всем ранее объявленным переменным, чьи имена начинаются с
varprefix
Соответствует всем ранее объявленным переменным, чьи имена начинаются с
varprefix
* Само собой разумеется, если переменная var инициализирована, то результатом выражения будет
$var.
Таблица B-5. Операции со строками |
|
Выражение |
Описание |
${#string} |
Длина строки $string |
${string:position} |
Извлечение подстроки из строки $string, |
|
начиная с позиции $position |
${string:position:length}
${string#substring}
Извлечение $length символов из строки $string, начиная с позиции $position
Поиск кратчайшего совпадения по шаблону $substring, в строке $string, поиск ведется с начала строки
${string##substring} |
Поиск самого длинного совпадения по шаблону |
|
$substring, в строке $string, поиск ведется с |
415

${string%substring}
${string%%substring}
${string/substring/replacement}
${string//substring/replacement}
${string/#substring/replacement}
Если в строке $string найдено соответствие шаблону $substring и найденая подстрока заканчивает строку $string, то она заменяется
подстрокой $replacement
начала строки
Поиск кратчайшего совпадения по шаблону $substring, в строке $string, поиск ведется с конца строки
Поиск самого длинного совпадения по шаблону $substring, в строке $string, поиск ведется с конца строки
Замена первой, найденой по шаблону $substring, подстроки на подстроку $replacement
Замена всех, найденых по шаблону $substring, подстрок на подстроку $replacement
Если в строке $string найдено соответствие шаблону $substring и найденая подстрока начинает строку $string, то она заменяется
подстрокой $replacement
expr match "$string" '$substring'
expr "$string" : '$substring'
expr index "$string" $substring
expr substr $string $position $length
expr match "$string" '\($substring\)'
expr "$string" : '\($substring\)'
expr match "$string" '.*\($substring\)'
expr "$string" : '.*\($substring\)'
* Где $substring -- регулярное выражение.
Таблица B-6. Прочие конструкции
Выражение
Описание
Квадратные скобки
Количество совпадений с шаблоном $substring* в строке $string, поиск начинается с начала строки
Количество совпадений с шаблоном $substring* в строке $string, поиск начинается с начала строки
Позиция (номер символа), первого найденого совпадения с шаблоном $substring, в строке
$string
Извлечение $length символов из строки $string, начиная с позиции $position
Извлечение подстроки с начала строки $string, совпадающей с шаблоном $substring*
Извлечение подстроки с начала строки $string, совпадающей с шаблоном $substring*
Извлечение подстроки с конца строки $string, совпадающей с шаблоном $substring*
Извлечение подстроки с конца строки $string, совпадающей с шаблоном $substring*
416

if [ CONDITION ]
if [[ CONDITION ]] Array[1]=element1
[a-z]
Фигурные скобки
${variable}
${!variable}
{ command1; command2 } {string1,string2,string3,...}
Круглые скобки
( command1; command2 )
Array=(element1 element2 element3)
result=$(COMMAND)
>(COMMAND)
<(COMMAND)
Двойные круглые скобки
(( var = 78 )) var=$(( 20 + 5 ))
Кавычки
"$variable" 'string'
Обратные кавычки
result=`COMMAND`
Проверка условия
Расширеный синтаксис операции проверки условия
Инициализация массива Диапазон символов в регулярных выражениях
Подстановка параметра
Косвенная ссылка на переменную
Блок кода Подстановка
Группа команд, исполняемая в подоболочке (subshell)
Инициализация массива
Команда исполняется в подоболочке, результат записывается в переменную
Подстановка процесса Подстановка процесса
Целочисленная арифметика
Арифметическое выражение, результат записывается в переменную
"Мягкие", или "нестрогие" кавычки "Строгие", или "полные" кавычки
Команда исполняется в подоболочке, результат записывается в переменную
Приложение C. Маленький учебник по Sed и Awk
В этом приложении содержится очень краткое описание приемов работы с утилитами обработки текста sed и awk. Здесь будут рассмотрены лишь несколько базовых команд, которых, в принципе, будет достаточно, чтобы научиться понимать простейшие конструкции sed и awk внутри сценариев на языке командной оболочки.
sed: неинтерактивный редактор текстовых файлов
417

awk: язык обработки шаблонов с C-подобным синтаксисом
При всех своих различиях, эти две утилиты обладают похожим синтаксисом, они обе умеют работать с регулярными выражениями, обе, по-умолчанию, читают данные с устройства stdin и обе выводят результат обработки на устройство stdout. Обе являются утилитами Unix-систем, и прекрасно могут взаимодействовать между собой. Вывод от одной может быть перенаправлен, по конвейеру, на вход другой. Их комбинирование придает сценариям, на языке командной оболочки, мощь и гибкость языка Perl.
Одно важное отличие состоит в том, что в случае с sed, сценарий легко может передавать дополнительные аргументы этой утилите, в то время, как в случае с awk (см. Пример 33-3 и Пример 9-22), это более сложная задача .
C.1. Sed
Sed -- это неинтерактивный строчный редактор. Он принимает текст либо с устройства stdin, либо из текстового файла, выполняет некоторые операции над строками и затем выводит результат на устройство stdout или в файл. Как правило, в сценариях, sed используется в конвейерной обработке данных, совместно с другими командами и утилитами.
Sed определяет, по заданному адресному пространству, над какими строками следует выполнить операции. [66] Адресное пространство строк задается либо их порядковыми номерами, либо шаблоном. Например, команда 3d заставит sed удалить третью строку, а команда /windows/d означает, что все строки, содержащие "windows", должны быть удалены.
Из всего разнообразия операций, мы остановимся на трех, используемых наиболее часто. Это p -- печать (на stdout), d -- удаление и s -- замена.
Таблица C-1. Основные операции sed
Операция |
Название Описание |
||
[диапазон |
строк]/p |
Печать [указанного диапазона строк] |
|
[диапазон |
строк]/d |
delete |
Удалить [указанный диапазон строк] |
s/pattern1/pattern2/ |
substitute |
Заменить первое встреченное соответствие шаблону |
|
|
|
|
pattern1, в строке, на pattern2 |
[диапазон |
|
substitute |
Заменить первое встреченное соответствие шаблону |
строк]/s/pattern1/pattern2/ |
|
pattern1, на pattern2, в указанном диапазоне строк |
|
[диапазон |
|
transform |
заменить любые символы из шаблона pattern1 на |
строк]/y/pattern1/pattern2/ |
|
соответствующие символы из pattern2, в указанном |
|
|
|
|
диапазоне строк (эквивалент команды tr) |
g |
|
global |
Операция выполняется над всеми найдеными |
|
|
|
соответствиями внутри каждой из заданных строк |
Без оператора g (global), операция замены будет производиться только для первого найденого совпадения, с заданным шаблоном, в каждой строке.
В отдельных случаях, операции sed необходимо заключать в кавычки.
sed -e '/^$/d' $filename
# Ключ -e говорит о том, что далее следует строка, которая должна интерпретироваться #+ как набор инструкций редактирования.
# (При передаче одной инструкции, ключ "-e" является необязательным.)
# "Строгие" кавычки ('') предотвращают интерпретацию символов регулярного выражения, #+ как специальных символов, командным интерпретатором.
418

#
# Действия производятся над строками, содержащимися в файле $filename.
В отдельных случаях, команды редактирования не работают в одиночных кавычках.
filename=file1.txt
pattern=BEGIN
# |
sed |
"/^$pattern/d" |
"$filename" |
# Результат вполне предсказуем. |
|
sed |
'/^$pattern/d' |
"$filename" |
дает иной результат. |
||
# |
|
В |
данном случае, в "строгих" кавычках (' ... '), |
||
#+ |
не |
происходит |
подстановки значения переменной "$pattern". |
Sed использует ключ -e для того, чтобы определить, что следующая строка является инструкцией, или набором инструкций, редактирования. Если инструкция является единственной, то использование этого ключа не является обязательным.
sed -n '/xzy/p' $filename |
строки, которые |
совпадают с указанным шаблоном. |
|
# Ключ -n заставляет sed вывести только те |
|||
# |
В противном случае (без ключа -n), будут выведены все строки. |
||
# |
Здесь, ключ -e не является обязательным, |
поскольку здесь |
стоит единственная команда. |
Таблица C-2. Примеры операций в sed
Операция |
Описание |
8d |
Удалить 8-ю строку. |
/^$/d |
Удалить все пустые строки. |
1,/^$/d |
Удалить все строки до первой пустой строки, включительно. |
/Jones/p |
Вывести строки, содержащие "Jones" (с ключом -n). |
s/Windows/Linux/ |
В каждой строке, заменить первое встретившееся слово "Windows" на слово |
|
"Linux". |
s/BSOD/stability/g В каждой строке, заменить все встретившиеся слова "BSOD" на "stability". |
|
s/ *$// |
Удалить все пробелы в конце каждой строки. |
s/00*/0/g |
Заменить все последовательности ведущих нулей одним символом "0". |
/GUI/d |
Удалить все строки, содержащие "GUI". |
s/GUI//g |
Удалить все найденые "GUI", оставляя остальную часть строки без изменений. |
Замена строки пустой строкой, эквивалентна удалению части строки, совпадающей с шаблоном. Остальная часть строки остается без изменений. Например, s/GUI//, изменит следующую строку
The most important parts of any application are its GUI and sound effects
на
The most important parts of any application are its and sound effects
Символ обратного слэша представляет символ перевода строки, как символ замены. В этом случае, замещающее выражение продолжается на следующей строке.
419

s/^ */\ /g
Эта инструкция заменит начальные пробелы в строке на символ перевода строки. Ожидаемый результат -- замена отступов в начале параграфа пустыми строками.
Указание диапазона строк, предшествующее одной, или более, инструкции может потребовать заключения инструкций в фигурные скобки, с соответствующими символами перевода строки.
/[0-9A-Za-z]/,/^$/{ /^$/d
}
В этом случае будут удалены только первые из нескольких, идущих подряд, пустых строк. Это может использоваться для установки однострочных интервалов в файле, оставляя, при этом, пустые строки между параграфами.
Быстрый способ установки двойных межстрочных интервалов в текстовых файлах -- sed G
filename.
Примеры использования sed в сценариях командной оболочки, вы найдете в:
1.Пример 33-1
2.Пример 33-2
3.Пример 12-3
4.Пример A-3
5.Пример 12-15
6.Пример 12-23
7.Пример A-13
8.Пример A-19
9.Пример 12-27
10.Пример 10-9
11.Пример 12-36
12.Пример A-2
13.Пример 12-13
14.Пример 12-11
15.Пример A-11
16.Пример 17-12
Ссылки на дополнительные сведения о sed, вы найдете в разделе Библиография.
420

C.2. Awk
Awk -- это полноценный язык обработки текстовой информации с синтаксисом, напоминающим синтаксис языка C. Он обладает довольно широким набором возможностей, однако, мы рассмотрим лишь некоторые из них -- наиболее употребимые в сценариях командной оболочки.
Awk "разбивает" каждую строку на отдельные поля. По-умолчанию, поля -- это последовательности символов, отделенные друг от друга пробелами, однако имеется возможность назначения других символов, в качестве разделителя полей. Awk анализирует и обрабатывает каждое поле в отдельности. Это делает его идеальным инструментом для работы со структурированными текстовыми файлами -- осбенно с таблицами.
Внутри сценариев командной оболочки, код awk, заключается в "строгие" (одиночные) кавычки и фигурные скобки.
awk '{print $3}' $filename
# Выводит содержимое 3-го поля из файла $filename на устройство stdout.
awk '{print $1 $5 $6}' $filename
# Выводит содержимое 1-го, 5-го и 6-го полей из файла $filename.
Только что, мы рассмотрели действие команды print. Еще, на чем мы остановимся -- это переменные. Awk работает с переменными подобно сценариям командной оболочки, но более гибко.
{ total += ${column_number} }
Эта команда добавит содержимое переменной column_number к переменной "total". Чтобы, в завершение вывести "total", можно использовать команду END, которая открывает блок кода, отрабатывающий после того, как будут обработаны все входные данные.
END { print total }
Команде END, соответствует команда BEGIN, которая открывает блок кода, отрабатывающий перед началом обработки входных данных.
Следующий пример демонстрирует применение awk для разбора текста в сценариях командной оболочки.
Пример C-1. Подсчет количества символов
#! /bin/sh
# letter-count.sh: Counting letter occurrences in a text file.
#
# Автор: nyal (nyal@voila.fr).
# Используется с разрешения автора сценария.
# Комментарии добавлены автором документа.
INIT_TAB_AWK=""
count_case=0 FILE_PARSE=$1
E_PARAMERR=65
421
usage() |
|
{ |
|
echo "Порядок использования: letter-count.sh имя_файла символы" 2>&1 |
|
# Например: |
./letter-count.sh filename.txt a b c |
exit $E_PARAMERR # Вызов сценария без аргументов. |
|
} |
|
if |
[ ! -f "$1" |
] ; then |
|
echo "Файл |
$1 не найден." 2>&1 |
fi |
usage |
# Вывод сообщения и выход. |
|
|
if [ -z "$2" ] ; then |
|
echo "$2: Не заданы символы для поиска." 2>&1 |
|
usage |
|
fi |
|
shift |
# Символы заданы. |
for letter in `echo $@` |
# Для каждого из них . . . |
do
INIT_TAB_AWK="$INIT_TAB_AWK tab_search[${count_case}] = \"$letter\"; final_tab[${count_case}] =
0;#"Передается как параметр в сценарий awk ниже. count_case=`expr $count_case + 1`
done
#DEBUG:
#echo $INIT_TAB_AWK;
cat $FILE_PARSE |
# Передать заданый файл по конвейеру в сценарий awk.
# --------------------------------------------------------------------------------
# От переводчика:
# В оригинальном тексте сценария стоит следующая строка:
#awk -v tab_search=0 -v final_tab=0 -v tab=0 -v nb_letter=0 -v chara=0 -v chara2=0 \
#
# с моим gawk 3.1.3 сценарий делается неработоспособным
# поэтому я взял на себя смелость несколько подправить эту строку,
# в результате она получилась такой: awk -v nb_letter=0 -v chara=0 -v chara2=0 \ "BEGIN { $INIT_TAB_AWK } \
{ split(\$0, tab, \"\"); \ for (chara in tab) \
{ for (chara2 in tab_search) \
{ if (tab_search[chara2] == tab[chara]) { final_tab[chara2]++ } } } } \ END { for (chara in final_tab) \
{ print tab_search[chara] \" => \" final_tab[chara] } }"
# --------------------------------------------------------------------------------
# Ничего сложного. . .
#+ Циклы for, проверка условия if, и пара специфических функций. exit $?
Более простые примеры использования awk в сценариях командной оболочки, вы найдете в:
1.Пример 11-11
2.Пример 16-7
3.Пример 12-27
4.Пример 33-3
5.Пример 9-22
6.Пример 11-17
7.Пример 27-2
8.Пример 27-3
422