Не найпростіше , але ви можете зробити щось на кшталт:
$ 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 класу A), або 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"