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