Выражение регулярного выражения для IP-адреса / CIDR в bash

Обрабатывайте аргументы с помощью bash, а не внешних процессов

for ARG in "${PARGS_ARR[@]}"
do
  # trim single quotes 
  ARG=${ARG//\'}

  # split by equals sign
  IFS="=" read ARGL ARGR <<< "$ARG"

  if [[ "$ARGL" == "-DnodeId" ]]; then
    NODE=$ARGR
  fi
done
0
08.03.2019, 13:47
1 ответ

Для правильной обработки проверки IP-адреса или CIDR используйте специально созданную для этого библиотечную функцию, такую ​​как cidrvalidate()Perl-функция в модуле Net::CIDR:

$ perl -MNet::CIDR=cidrvalidate -e 'printf("%s\n", cidrvalidate($ARGV[0]) ? "valid" : "invalid")' -- 1.2.3.0/24
valid

$ perl -MNet::CIDR=cidrvalidate -e 'printf("%s\n", cidrvalidate($ARGV[0]) ? "valid" : "invalid")' -- 1.2.3.0/2
invalid

$ perl -MNet::CIDR=cidrvalidate -e 'printf("%s\n", cidrvalidate($ARGV[0]) ? "valid" : "invalid")' -- 1.2.3.0
valid

См. perldoc Net::CIDRдля того, что еще может сделать эта библиотека.

--не является необходимым в приведенных выше примерах, но будет использоваться для произвольного ввода пользователем, иначе этот ввод будет принят как вариант perl, если он начинается с -.

Приведенные ниже подходы являются вариантами вашей попытки, в которой не учитываются недопустимые маски сети.


Целое положительное десятичное число от 0 до 255 может соответствовать

[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5]

Целое положительное десятичное число от 0 до 32 может соответствовать

[0-9]|[12][0-9]|3[012]

Использование этого:

#!/bin/bash

n='([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])'
m='([0-9]|[12][0-9]|3[012])'

IFS= read -rp 'Input: ' ipaddr

if [[ $ipaddr =~ ^$n(\.$n){3}/$m$ ]]; then
    printf '"%s" is a valid CIDR\n' "$ipaddr"
else
    printf '"%s" is not valid\n' "$ipaddr"
fi

Выражение

^$n(\.$n){3}/$m$

будет расширяться до полного регулярного выражения для действительного CIDR, охватывающего всю длину данной строки.


Другой очевидный способ сделать это — прочитать числа в заданной строке и проверить, находятся ли первые четыре в диапазоне 0 -255, а пятое — в диапазоне 0 -32:

#!/bin/bash

IFS='./' read -rp 'Input: ' a b c d e

for var in "$a" "$b" "$c" "$d" "$e"; do
    case $var in
        ""|*[!0123456789]*) 
            printf 'not a valid number: %s\n' "$var"
            exit 1
    esac
done

ipaddr="$a.$b.$c.$d/$e"

if [ "$a" -ge 0 ] && [ "$a" -le 255 ] &&
   [ "$b" -ge 0 ] && [ "$b" -le 255 ] &&
   [ "$c" -ge 0 ] && [ "$c" -le 255 ] &&
   [ "$d" -ge 0 ] && [ "$d" -le 255 ] &&
   [ "$e" -ge 0 ] && [ "$e" -le 32  ]
then
    printf '"%s" is a valid CIDR\n' "$ipaddr"
else
    printf '"%s" is not valid\n' "$ipaddr"
fi

Здесь мы читаем пять слов в пять переменных. Введенная строка разбивается на слова .и /при чтении (, что означает, что 3/3/3/3.2будет проанализировано как допустимое, но см. $ipaddrв коде ). Любые считанные целочисленные данные, отличные от -, вызовут выход сценария. Затем мы начинаем проверять их значения на соответствие допустимым диапазонам. Если какой-либо тест не пройден, введенный адрес недействителен.

4
28.01.2020, 02:30

Теги

Похожие вопросы