Дейв Тейлор - Сценарии командной оболочки. Linux, OS X и Unix. 2-е издание
- Название:Сценарии командной оболочки. Linux, OS X и Unix. 2-е издание
- Автор:
- Жанр:
- Издательство:Питер
- Год:2017
- Город:СПб.
- ISBN:978-5-496-03029-8
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Дейв Тейлор - Сценарии командной оболочки. Linux, OS X и Unix. 2-е издание краткое содержание
Цель этой книги — продемонстрировать практические приемы программирования сценариев на bash и познакомить с самыми распространенными утилитами на коротких и компактных примерах, не вдаваясь в излишние подробности. Экспериментируйте с этими сценариями — ломайте, исправляйте и приспосабливайте их под свои нужды, чтобы понять, как они работают. Только так вы сможете решать самые сложные задачи.
Сценарии командной оболочки. Linux, OS X и Unix. 2-е издание - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
$ brew install coreutils
После установки GNU-версии утилиты date определить, високосный ли указанный год, можно с помощью самой программы, без необходимости путаться в сложных правилах о годах, кратных 4, но не 100, и других:
if [$(date 12/31/$year +%j) −eq 366]
Иными словами, если последним днем года является 366-й, этот год — високосный.
Еще одна замечательная особенность GNU date — возможность вернуться назад во времени. Стандартная команда date в системе Unix основана на понятии «нулевого времени» или дате эпохи: 00:00:00 по Гринвичу 1 января 1970 года. Хотите узнать что-нибудь о происходившем в 1965? Тогда вам не повезло. К счастью, с тремя остроумными сценариями в этой главе вы сможете в полной мере использовать преимущества GNU date.
№ 99. Определение дня недели в указанную дату в прошлом
Вкратце: в какой день недели вы родились? В какой день недели Нил Армстронг и Базз Олдрин ступили на Луну? Сценарий в листинге 15.1 поможет вам быстро найти ответы на эти типичные вопросы и наглядно продемонстрирует мощь GNU date.
Код
Листинг 15.1.Сценарий dayinpast
#!/bin/bash
# dayinpast — получая дату, сообщает соответствующий ей день недели.
if [$# −ne 3]; then
··echo "Usage: $(basename $0) mon day year" >&2
··echo " with just numerical values (ex: 7 7 1776)" >&2
··exit 1
fi
date −version > /dev/null 2>&1 # Отбросить сообщение об ошибке, если появится.
baddate="$?"····················# И сохранить только возвращаемый код.
if [! $baddate]; then
··date −d $1/$2/$3 +"That was a %A."
else
··if [$2 −lt 10]; then
····pattern=" $2[^0–9]"
··else
····pattern="$2[^0–9]"
··fi
··dayofweek="$(
ncal $1 $3 | grep "$pattern" | −c— c1-2)"
··case $dayofweek in
····Su) echo "That was a Sunday.";····;;
····Mo) echo "That was a Monday.";····;;
····Tu) echo "That was a Tuesday.";··;;
····We) echo "That was a Wednesday.";;;
····Th) echo "That was a Thursday.";··;;
····Fr) echo "That was a Friday.";····;;
····Sa) echo "That was a Saturday.";··;;
··esac
fi
exit 0
Как это работает
Мы так нахваливали GNU date, и знаете почему? А потому, что весь сценарий сводится к к единственной команде в .
До смешного просто.
Если требуемая версия date недоступна, сценарий использует ncal , разновидность простой программы cal, которая представляет указанный месяц в любопытном, он очень полезном (!) формате:
$ ncal 8 1990
····August 1990
Mo···· 6 13 20 27
Tu···· 7 14 21 28
We··1··8 15 22 29
Th··2··9 16 23 30
Fr··3 10 17 24 31
Sa··4 11 18 25
Su··5 12 19 26
Когда есть эта информация, для определения дня недели достаточно найти строку с соответствующим днем месяца и преобразовать двухбуквенное сокращение в полное название.
Запуск сценария
Нил Армстронг и Базз Олдрин прилунились на Базе Спокойствия 20 июля 1969 года, и, как сообщают результаты в листинге 15.2, это было воскресенье.
Листинг 15.2.Запуск сценария dayinpast с датой посадки Армстронга и Олдрина на Луну
$ dayinpast 7 20 1969
That was a Sunday.
День «Д» высадки союзнических войск в Нормандии, 6 июня 1944 года:
$ dayinpast 6 6 1944
That was a Tuesday.
А вот еще пример, день принятия Декларации о независимости США, 4 июля 1776 года:
$ dayinpast 7 4 1776
That was a Thursday.
Усовершенствование сценария
Все сценарии в этой главе принимают входные данные в формате месяц день год , но было бы хорошо дать пользователям возможность указывать данные в более привычном им виде, например: месяц/день/год . К счастью, это совсем несложно, и отличной отправной точкой вам послужит сценарий № 3 в главе 1.
№ 100. Вычисление дней между датами
Сколько дней вы живете? Сколько дней прошло с того момента, как ваши родители встретились? Подобные вопросы, связанные с определением разности между датами, возникают часто, но вычислить ответ на них обычно бывает непросто. И снова на помощь нам приходит утилита GNU date.
Идея обоих сценариев, № 100 и № 101, заключается в том, что суммируются дни от первой даты до конца года, дни от начала года до второй даты и число дней во всех промежуточных годах. Один и тот же подход можно использовать для вычисления количества дней, прошедших с некоторой даты в прошлом (этот сценарий), и количества дней, оставшихся до некоторой даты в будущем (сценарий № 101).
Листинг 15.3 довольно длинный. Готовы?
Код
Листинг 15.3.Сценарий daysago
··#!/bin/bash
··# daysago — получая дату в формате месяц/день/год, вычисляет количество
··#·· дней, прошедших от нее до текущего дня, учитывая високосные годы, и пр.
··# Если вы используете Linux, замените "$(which gdate)" на "$(which date)".
··#·· Если вы используете OS X, установите пакет coreutils с помощью brew или
··#·· из исходного кода, чтобы получить команду gdate.
··date="$(which gdate)"
··function daysInMonth
··{
····case $1 in
······1|3|5|7|8|10|12) dim=31;; # Постоянное значение
······4|6|9|11········) dim=30;;
······2··············) dim=29;; # Зависит от года: високосный/невисокосный
······*··············) dim=-1;; # Неизвестный месяц
····esac
··}
··function isleap
··{
····# Возвращает ненулевое значение в $leapyear, если $1 — високосный год.
····leapyear=$($date −d 12/31/$1 +%j | grep 366)
··}
··#######################
··#### ОСНОВНОЙ БЛОК
··#######################
··if [$# −ne 3]; then
····echo "Usage: $(basename $0) mon day year"
····echo " with just numerical values (ex: 7 7 1776)"
····exit 1
··fi
··$date −version > /dev/null 2>&1 # Отбросить сообщение об ошибке, если появится.
··if [$? -ne 0]; then
····echo "Sorry, but $(basename $0) can't run without GNU date." >&2
····exit 1
··fi
··eval $($date "+thismon=%m;thisday=%d;thisyear=%Y;dayofyear=%j")
··startmon=$1; startday=$2; startyear=$3
··daysInMonth $startmon # Инициализирует глобальную переменную dim.
··if [$startday −lt 0 −o $startday −gt $dim]; then
····echo "Invalid: Month #$startmon only has $dim days." >&2
····exit 1
··fi
··if [$startmon −eq 2 −a $startday −eq 29]; then
····isleap $startyear
····if [-z "$leapyear"]; then
······echo "Invalid: $startyear wasn't a leap year; February had 28 days." >&2
······exit 1
····fi
··fi
··#######################
··#### ВЫЧИСЛЕНИЕ КОЛИЧЕСТВА ДНЕЙ
··#######################
Интервал:
Закладка: