Мендель Купер - Искусство программирования на языке сценариев командной оболочки
- Название:Искусство программирования на языке сценариев командной оболочки
- Автор:
- Жанр:
- Издательство:неизвестно
- Год:неизвестен
- ISBN:нет данных
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Мендель Купер - Искусство программирования на языке сценариев командной оболочки краткое содержание
Данное руководство не предполагает наличие у читателя познаний в области программирования на языке сценариев, однако, быстро восполняет этот недостаток, постепенно, шаг за шагом раскрывая мудрость и красоту UNIX. Это руководство может рассматриваться как учебник, предназначенный для самостоятельного изучения или как справочник по программированию на shell. Руководство снабжено серией хорошо прокомментированных примеров, поскольку лучший путь к изучению языка сценариев -- это написание сценариев.
Искусство программирования на языке сценариев командной оболочки - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
GENERATIONS=10 # Максимальное число поколений.
NONE_ALIVE=80 # Код завершения на случай,
#+ если не осталось ни одной "живой" особи.
TRUE=0
FALSE=1
ALIVE=0
DEAD=1
avar= # Текущее поколение.
generation=0 # Инициализация счетчика поколений.
# =================================================================
let "cells = $ROWS * $COLS"
# Количество ячеек на игровом поле.
declare -a initial # Массивы ячеек.
declare -a current
display ()
{
alive=0 # Количество "живых" особей.
# Изначально -- ноль.
declare -a arr
arr=( `echo "$1"` ) # Преобразовать аргумент в массив.
element_count=${#arr[*]}
local i
local rowcheck
for ((i=0; i<$element_count; i++))
do
# Символ перевода строки -- в конец каждой строки.
let "rowcheck = $i % ROWS"
if [ "$rowcheck" -eq 0 ]
then
echo # Перевод строки.
echo -n " " # Выравнивание.
fi
cell=${arr[i]}
if [ "$cell" = . ]
then
let "alive += 1"
fi
echo -n "$cell" | sed -e 's/_/ /g'
# Вывести массив, по пути заменяя символы подчеркивания на пробелы.
done
return
}
IsValid () # Проверка корректности координат ячейки.
{
if [ -z "$1" -o -z "$2" ] # Проверка наличия входных аргументов.
then
return $FALSE
fi
local row
local lower_limit=0 # Запрет на отрицательные координаты.
local upper_limit
local left
local right
let "upper_limit = $ROWS * $COLS - 1" # Номер последней ячейки на игровом поле.
if [ "$1" -lt "$lower_limit" -o "$1" -gt "$upper_limit" ]
then
return $FALSE # Выход за границы массива.
fi
row=$2
let "left = $row * $ROWS" # Левая граница.
let "right = $left + $COLS - 1" # Правая граница.
if [ "$1" -lt "$left" -o "$1" -gt "$right" ]
then
return $FALSE # Выхол за нижнюю строку.
fi
return $TRUE # Координаты корректны.
}
IsAlive () # Проверка наличия "живой" особи в ячейке.
# Принимает массив и номер ячейки в качестве входных аргументов.
{
GetCount "$1" $2 # Подсчитать кол-во "живых" соседей.
local nhbd=$?
if [ "$nhbd" -eq "$BIRTH" ] # "Живая".
then
return $ALIVE
fi
if [ "$3" = "." -a "$nhbd" -eq "$SURVIVE" ]
then # "Живая" если перед этим была "живая".
return $ALIVE
fi
return $DEAD # По-умолчанию.
}
GetCount () # Подсчет "живых" соседей.
# Необходимо 2 аргумента:
# $1) переменная-массив
# $2) cell номер ячейки
{
local cell_number=$2
local array
local top
local center
local bottom
local r
local row
local i
local t_top
local t_cen
local t_bot
local count=0
local ROW_NHBD=3
array=( `echo "$1"` )
let "top = $cell_number - $COLS - 1" # Номера соседних ячеек.
let "center = $cell_number - 1"
let "bottom = $cell_number + $COLS - 1"
let "r = $cell_number / $ROWS"
for ((i=0; i<$ROW_NHBD; i++)) # Просмотр слева-направо.
do
let "t_top = $top + $i"
let "t_cen = $center + $i"
let "t_bot = $bottom + $i"
let "row = $r" # Пройти по соседям в средней строке.
IsValid $t_cen $row # Координаты корректны?
if [ $? -eq "$TRUE" ]
then
if [ ${array[$t_cen]} = "$ALIVE1" ] # "Живая"?
then # Да!
let "count += 1" # Нарастить счетчик.
fi
fi
let "row = $r - 1" # По верхней строке.
IsValid $t_top $row
if [ $? -eq "$TRUE" ]
then
if [ ${array[$t_top]} = "$ALIVE1" ]
then
let "count += 1"
fi
fi
let "row = $r + 1" # По нижней строке.
IsValid $t_bot $row
if [ $? -eq "$TRUE" ]
then
if [ ${array[$t_bot]} = "$ALIVE1" ]
then
let "count += 1"
fi
fi
done
if [ ${array[$cell_number]} = "$ALIVE1" ]
then
let "count -= 1" # Убедиться, что сама проверяемая ячейка
fi #+ не была подсчитана.
return $count
}
next_gen () # Обновить массив, в котором содержится информация о новом "поколении".
{
local array
local i=0
array=( `echo "$1"` ) # Преобразовать в массив.
while [ "$i" -lt "$cells" ]
do
IsAlive "$1" $i ${array[$i]} # "Живая"?
if [ $? -eq "$ALIVE" ]
then # Если "живая", то
array[$i]=. #+ записать точку.
else
array[$i]="_" # Иначе -- символ подчеркивания
fi #+ (который позднее заменится на пробел).
let "i += 1"
done
# let "generation += 1" # Увеличить счетчик поколений.
# Подготовка переменных, для передачи в функцию "display".
avar=`echo ${array[@]}` # Преобразовать массив в строку.
display "$avar" # Вывести его.
echo; echo
echo "Поколение $generation -- живых особей $alive"
if [ "$alive" -eq 0 ]
then
echo
echo "Преждеверменное завершение: не осталось ни одной живой особи!"
exit $NONE_ALIVE # Нет смысла продолжать
fi #+ если не осталось ни одной живой особи
}
# =========================================================
# main ()
# Загрузить начальное поколение из файла.
initial=( `cat "$startfile" | sed -e '/#/d' | tr -d '\n' |\
sed -e 's/\./\. /g' -e 's/_/_ /g'` )
# Удалить строки, начинающиеся с символа '#' -- комментарии.
# Удалить строки перевода строки и вставить пробелы между элементами.
clear # Очистка экрана.
echo # Заголовок
echo "======================="
echo " $GENERATIONS поколений"
echo " в"
echo " игре \" ЖИЗНЬ\""
echo "======================="
# -------- Вывести первое поколение. --------
Gen0=`echo ${initial[@]}`
display "$Gen0" # Тлько вывод.
echo; echo
echo "Поколение $generation -- живых особей $alive"
# -------------------------------------------
let "generation += 1" # Нарастить счетчик поколений.
echo
# ------- Вывести второе поколение. -------
Cur=`echo ${initial[@]}`
next_gen "$Cur" # Обновить и вывести.
# ------------------------------------------
let "generation += 1" # Нарастить счетчик поколений.
# ------ Основной цикл игры ------
while [ "$generation" -le "$GENERATIONS" ]
do
Cur="$avar"
next_gen "$Cur"
let "generation += 1"
done
# ==============================================================
echo
exit 0
# --------------------------------------------------------------
# Этот сценарий имеет недоработку.
# Граничные ячейки сверху, снизу и сбоков остаются пустыми.
# Упражнение: Доработайте сценарий таким образом, чтобы ,
# + левая и правая стороны как бы "соприкасались",
# + так же и верхняя и нижняя стороны.
Пример A-12. Файл с первым поколением для игры "Жизнь"
# Это файл-пример, содержащий "поколение 0", для сценария "life.sh".
# --------------------------------------------------------------
# Игровое поле имеет размер 10 x 10, точкой обозначается "живая" особь,
#+ символом подчеркивания -- пустая ячейка. Мы не можем использовать пробелы,
#+ для обозначения пустых ячеек, из-за особенностей строения массивов в Bash.
# [Упражнение для читателей: объясните, почему?.]
#
# Строки, начинающиеся с символа '#' считаются комментариями, сценарий их игнорирует.
__.__..___
___._.____
____.___..
_._______.
____._____
..__...___
____._____
___...____
__.._..___
_..___..__
+++
Следующие два сценария предоставил Mark Moraes, из университета в Торонто. См. файл "Moraes-COPYRIGHT", который содержит указание на авторские права.
Пример A-13. behead: Удаление заголовков из электронных писем и новостей
#! /bin/sh
# Удаление заголовков из электронных писем и новостей т.е. до первой
# пустой строки
# Mark Moraes, Университет в Торонто
# ==> Такие комментарии добавлены автором документа.
if [ $# -eq 0 ]; then
# ==> Если входной аргумент не задан (файл), то выводить результат на stdin.
sed -e '1,/^$/d' -e '/^[ ]*$/d'
# --> Удалить пустые строки и все строки предшествующие им
else
# ==> Если аргумент командной строки задан, то использовать его как имя файла.
for i do
sed -e '1,/^$/d' -e '/^[ ]*$/d' $i
# --> То же, что и выше.
done
fi
# ==> Упражнение: Добавьте проверку на наличие ошибок.
# ==>
# ==> Обратите внимание -- как похожи маленькие сценарии sed, за исключением передачи аргумента.
# ==> Можно ли его оформит в виде функции? Почему да или почему нет?
Пример A-14. ftpget: Скачивание файлов по ftp
#! /bin/sh
# $Id: ftpget,v 1.2 91/05/07 21:15:43 moraes Exp $
Читать дальшеИнтервал:
Закладка: