Перевод статьи: Validating an IP Address in a Bash Script
26 июня 2008, Митч Фрэзер (Mitch Frazier)
Я часто пишу об использовании массивов bash и о регулярных выражениях bash, поэтому решил привести более полезный пример их использования для проверки правильности IP-адресов.
Задача очевидна: IP-адреса являются 32-битными значениями, записанными как четыре числа (отдельные байты IP-адреса), разделённых точками. Каждое из четырёх чисел может принимать значение в диапазоне от 0 до 255.
Следующий сценарий bash содержит функцию, которая возвращает истину, если её передан правильный IP-адрес и ложь в противном случае. В bash под истиной понимают завершение с нулевым кодом, всё остальное означает ложь. Код команды/функции bash помещается в переменную "$?".
#!/bin/bash # Проверка правильности IP-адреса: # Способ применения: # valid_ip IP_АДРЕС # if [[ $? -eq 0 ]]; then echo good; else echo bad; fi # ИЛИ # if valid_ip IP_ADDRESS; then echo good; else echo bad; fi # function valid_ip() { local ip=$1 local stat=1 if [[ $ip =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then OIFS=$IFS IFS='.' ip=($ip) IFS=$OIFS [[ ${ip[0]} -le 255 && ${ip[1]} -le 255 \ && ${ip[2]} -le 255 && ${ip[3]} -le 255 ]] stat=$? fi return $stat } # При непосредственном запуске выполним несколько проверок. if [[ "$(basename $0 .sh)" == 'valid_ip' ]]; then ips=' 4.2.2.2 a.b.c.d 192.168.1.1 0.0.0.0 255.255.255.255 255.255.255.256 192.168.0.1 192.168.0 1234.123.123.123 ' for ip in $ips do if valid_ip $ip; then stat='good'; else stat='bad'; fi printf "%-20s: %s\n" "$ip" "$stat" done fi
Если сохранить этот сценарий под именем "valid_ip.sh" и запустить его напрямую, он проведёт несколько проверок и выведет результаты:
# sh valid_ip.sh 4.2.2.2 : good a.b.c.d : bad 192.168.1.1 : good 0.0.0.0 : good 255.255.255.255 : good 255.255.255.256 : bad 192.168.0.1 : good 192.168.0 : bad 1234.123.123.123 : bad
В функции valid_ip, чтобы удостовериться в том, что рассматриваемый IP-адрес состоит из четырёх разделённых точками чисел, используется регулярное выражение в операторе if:
if [[ $ip =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
Если проверка пройдена, код внутри оператора if разделяет рассматриваемый IP-адрес на четыре части по точкам и помещает части в массив:
OIFS=$IFS IFS='.' ip=($ip) IFS=$OIFS
Эти действия меняют переменную bash, которая называется "внутренний разделитель полей" (Internal Field Separator). Обычно она используется для обработки слов, разделённых пробелами, по после этого bash будет использовать для разделения полей точки. Поместим значение рассматриваемого IP-адреса внутрь скобок и присвоим их значение массиву, поместив каждое из полей, разделённых точками, в отдельную ячейку массива. Теперь проверим отдельные поля, чтобы удостовериться в том, что они меньше или равны 255. Результат проверки сохраним, так чтобы его можно было вернуть в качестве значения функции:
[[ ${ip[0]} -le 255 && ${ip[1]} -le 255 \ && ${ip[2]} -le 255 && ${ip[3]} -le 255 ]] stat=$?
Отметим, что не обязательно проводить проверку равно ли число нулю или оно больше нуля, так как проверка регулярным выражением уже отфильтровала всё, что не состоит из точек и цифр.
Митч Фрэзер (Mitch Frazier) является помощником редактора в Linux Journal и веб-редактором в linuxjournal.com.