Не самый простой , но вы можете сделать что-то вроде:
$ IP=109.96.77.15
$ echo "$((${-+"(${IP//./"+256*("}))))"}&255))"
109
$ echo "$((${-+"(${IP//./"+256*("}))))"}>>8&255))"
96
$ echo "$((${-+"(${IP//./"+256*("}))))"}>>16&255))"
77
$ echo "$((${-+"(${IP//./"+256*("}))))"}>>24&255))"
15
Это должно работать в ksh93 (где , что ${var//pattern/replacement}оператор приходит от), bash4.3+, BusyBox sh, yash, mkshи zsh, хотя, конечно , в zsh, есть гораздо более простые подходы . В старых версиях bashвам нужно будет удалить внутренние кавычки. Это работает с теми внутренними кавычками, удаленными в большинстве других оболочек, но не ksh93.
Это предполагает, что $IPсодержит правильное четырехзначное представление адреса IPv4 (хотя это также будет работать для четырехугольных представлений типа 0x6d.0x60.0x4d.0xf(и даже восьмеричных в некоторых оболочках), но вывести значения в десятичном виде). Если содержимое $IPприходит из ненадежного источника, это равносильно уязвимости, связанной с внедрением команд.
В принципе, так как мы заменяем каждый .в $IPс +256*(, мы в конечном итоге оценка:
$(( (109+256*(96+256*(77+256*(15))))>> x &255 ))
Таким образом , мы построения 32 разрядное целое число из этих 4 байта , как IPv4 - адрес в конечном счете , является (хотя и с байты в обратном порядке ) ¹ , а затем , используя >>, &битовые операторы для извлечения соответствующих байтов.
Мы используем ${param+value}стандартный оператор (здесь, $-который гарантированно будет всегда установлен), а не просто valueпотому, что в противном случае арифметический синтаксический анализатор будет жаловаться на несовпадающие скобки. Оболочка здесь может найти закрытие ))для открытия $((, а затем выполнить расширения внутри, что приведет к вычислению арифметического выражения.
С $(((${IP//./"+256*("}))))&255))вместо этого, оболочка будет рассматривать второй и третий )МЕЕТСЯ как закрытие ))для $((и сообщит об ошибке.
В ksh93 вы также можете сделать:
$ echo "${IP/@(*).@(*).@(*).@(*)/\2}"
96
bash, mksh, zsh Скопировали ksh93 игровую ${var/pattern/replacement}оператора , но не то, что обработка части захвата-группы. zshподдерживает его с другим синтаксисом:
$ setopt extendedglob # for (#b)
$ echo ${IP/(#b)(*).(*).(*).(*)/$match[2]}'
96
bashподдерживает некоторую форму обработки группы захвата в своем операторе сопоставления регулярных выражений , но не в ${var/pattern/replacement}.
POSIXly, вы бы использовали:
(IFS=.; set -o noglob; set -- $IP; printf '%s\n' "$2")
noglob, Чтобы избежать неприятных сюрпризов для значений , $IPкак 10.*.*.*, подоболочка ограничить сферу действия этих изменений параметров и $IFS.
Address IPv4-адрес - это всего лишь 32-разрядное целое число, а, например, 127.0.0.1 - это лишь одно из многих (хотя и наиболее распространенных) текстовых представлений. Тот же типичный IPv4-адрес интерфейса обратной связи также может быть представлен как 0x7f000001 или 127.1 (возможно, здесь более уместно сказать, что это 1адрес в сети класса 127.0 / 8), или 0177.0.1, или другими комбинациями 1 до 4 чисел, выраженных как восьмеричное, десятичное или шестнадцатеричное. Вы можете передать все это, pingнапример, и увидите, что все они будут пинговать localhost.
Если вы не возражаете против побочного эффекта установки произвольной временной переменной (здесь $n), в bashили ksh93или zsh -o octalzeroesили lksh -o posix, вы можете просто преобразовать все эти представления обратно в 32-битное целое число с помощью:
$((n=32,(${IP//./"<<(n-=8))+("})))
А затем извлеките все компоненты с помощью >>/ &комбинаций, как указано выше.
$ IP=0x7f000001
$ echo "$((n=32,(${IP//./"<<(n-=8))+("})))"
2130706433
$ IP=127.1
$ echo "$((n=32,(${IP//./"<<(n-=8))+("})))"
2130706433
$ echo "$((n=32,((${IP//./"<<(n-=8))+("}))>>24&255))"
127
$ perl -MSocket -le 'print unpack("L>", inet_aton("127.0.0.1"))'
2130706433
mkshиспользует 32-разрядные целые числа со знаком для своих арифметических выражений, вы можете использовать $((# n=32,...))их для принудительного использования 32-разрядных чисел без знака (и posixвозможность распознавать восьмеричные константы).
IFSдляreadтам:IFS=. read -a ArrIP<<<"$IP"