Не самый простой , но вы можете сделать что-то вроде:
$ 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}
оператор приходит от), bash
4.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"