Еще один интересный аспект сценария — регулярные выражения, наиболее замысловатое из которых находится в строке
. Понять эту строку проще, если развернуть операцию подстановки, выполняемую sed. Подстановка всегда имеет вид s/old/new/ ; в данном случае шаблон old описывает строку, начинающуюся с ноля или более дефисов (-), за которыми следует любое количество цифр (как вы помните, [: digit: ] — это форма записи класса символов в ANSI, представляющего собой произвольную цифру, а звездочка (*) обозначает ноль или более вхождений предыдущего шаблона). Шаблон new описывает, чем заменить совпадение с шаблоном old , и в данном случае это всего лишь //, то есть пустой шаблон. Его удобно использовать, когда требуется просто удалить совпадения с шаблоном old . Данная операция подстановки фактически удаляет все цифры и дефисы так, что ввод -31f превращается в f и мы получаем возможность определить шкалу измерения температуры. После этого команда tr нормализует результат, преобразуя его в верхний регистр, то есть строка -31f, например, превращается в F.
Другое выражение sed выполняет противоположную операцию
: оно удаляет все, что не является частью числа, используя оператор ^ для инвертирования совпадения с любым символом в классе [: digit: ]. (В большинстве языков программирования инвертирование выполняет оператор!.) В результате получается значение для преобразования с применением соответствующей формулы.
Сценарий имеет простой и понятный формат входных данных, хотя и необычный для команд Unix. Сценарию передается числовое значение с необязательным символом в конце, обозначающим шкалу; в отсутствие этого символа предполагается, что значение температуры представлено в градусах Фаренгейта.
Чтобы узнать температуру в градусах Цельсия и Кельвина, эквивалентную 0° Фаренгейта, введите 0F. Чтобы узнать температуру в градусах Цельсия и Фаренгейта, эквивалентную 100° Кельвина, введите 100K. А чтобы узнать температуру в градусах Кельвина и Фаренгейта, эквивалентную 100° Цельсия, введите 10 °C.
Похожий прием использования односимвольного обозначения в конце мы увидим в главе 7, в сценарии № 60, который выполняет преобразования между валютами.
В листинге 3.9 показано несколько примеров преобразования температур.
Листинг 3.9.Тестирование сценария convertatemp несколькими преобразованиями
$ convertatemp 212
Fahrenheit = 212
Celsius = 100.00
Kelvin = 373.15
$ convertatemp 10 °C
Fahrenheit = 212.00
Celsius = 100
Kelvin = 373.15
$ convertatemp 100K
Fahrenheit = -279.67
Celsius = -173.15
Kelvin = 100
Усовершенствование сценария
В сценарий можно добавить поддержку нескольких флагов, чтобы ограничить вывод единственным результатом. Например, команда convertatemp −c 100F выводила бы только значение в градусах Цельсия, эквивалентное 100° Фаренгейта. Это помогло бы также упростить использование данного сценария внутри других.
№ 25. Вычисление платежей по кредиту
Другой распространенный вид вычислений, который наверняка пригодится пользователям — оценка платежей по кредиту. Сценарий в листинге 3.10 помогает также ответить на вопрос: «Куда потратить премию?», — и еще один, связанный с ним: «Могу ли я наконец позволить себе купить новую Tesla?».
Формула вычисления платежей, основанная на сумме кредита, процентах и его продолжительности, выглядит непростой, тем не менее грамотное использование переменных может помочь обуздать этого математического зверя и сделать вычисления на удивление простыми и понятными.
Листинг 3.10.Сценарий loancalc
··#!/bin/bash
··# loancalc — По заданной сумме кредита, процентной ставке
··#·· и продолжительности (в годах), вычисляет суммы платежей
··# Формула: M = P * (J / (1 — (1 + J) ^ −N)),
··#·· где P = сумма кредита, J = месячная процентная ставка, N = протяженность·· #·· (месяцев).
··# Обычно пользователи вводят P, I (годовая процентная ставка) и L (протяженность·· #·· в годах).
··. library.sh # Подключить библиотечный сценарий.
··if [$# −ne 3]; then
····echo "Usage: $0 principal interest loan-duration-years" >&2
····exit 1
··fi
P=$1 I=$2 L=$3
Читать дальше