Nie najłatwiej , ale możesz zrobić coś takiego:
$ 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
To powinno działać w ksh93 (jeżeli ${var//pattern/replacement}operator pochodzi), bash4.3+, BusyBox sh, yash, mkshi zsh, choć oczywiście w zshnie są o wiele prostsze sposoby . W starszych wersjach bashtrzeba by usunąć wewnętrzne cytaty. Działa z tymi wewnętrznymi cudzysłowami usuniętymi również w większości innych powłok, ale nie w ksh93.
Zakłada się, że $IPzawiera prawidłową reprezentację adresu IPv4 w postaci dziesiętno-dziesiętnej (choć działałoby to również w przypadku reprezentacji cztero-szesnastkowych, takich jak 0x6d.0x60.0x4d.0xf(a nawet ósemkowa w niektórych powłokach), ale wyświetlałby wartości dziesiętnie). Jeśli zawartość $IPpochodzi z niezaufanego źródła, oznacza to lukę w zabezpieczeniach polegającą na wstrzykiwaniu poleceń.
Zasadniczo, jak jesteśmy zastępując każdy .w $IPz +256*(, skończymy oceny:
$(( (109+256*(96+256*(77+256*(15))))>> x &255 ))
Więc jesteśmy konstruowania 32 bitową liczbę całkowitą z tych 4 bajtów, takich jak adres IPv4 ostatecznie jest (choć z bajty odwrócone) ¹, a następnie przy użyciu >>, &bitowe operatorów wyodrębnić odpowiednie bajty.
Używamy ${param+value}standardowego operatora (tutaj $-zawsze gwarantuje się ustawienie) zamiast tego, valueponieważ w przeciwnym razie parser arytmetyczny narzekałby na niedopasowany nawias. Powłoka tutaj może znaleźć zamknięcie ))dla otwarcia $((, a następnie wykonać rozszerzenia wewnątrz, które spowodują wyrażenie arytmetyczne do oceny.
Dzięki $(((${IP//./"+256*("}))))&255))zamiast, powłoka potraktuje drugi i trzeci )s tam jako zamknięcie ))dla $((i zgłosić błąd składni.
W ksh93 możesz także:
$ echo "${IP/@(*).@(*).@(*).@(*)/\2}"
96
bash, mksh, zsh Zostały skopiowane ksh93 męska ${var/pattern/replacement}operatora, ale nie, że grupa przechwytywania obsługi część. zshobsługuje go z inną składnią:
$ setopt extendedglob # for (#b)
$ echo ${IP/(#b)(*).(*).(*).(*)/$match[2]}'
96
bashobsługuje pewną formę obsługi grup przechwytywania w operatorze dopasowania wyrażeń regularnych , ale nie w ${var/pattern/replacement}.
POSIXly użyłbyś:
(IFS=.; set -o noglob; set -- $IP; printf '%s\n' "$2")
noglobAby uniknąć złych niespodzianek dla wartości $IPjak 10.*.*.*, podpowłoki aby ograniczyć zakres tych zmian do opcji i $IFS.
¹ Adres IPv4 to tylko 32-bitowa liczba całkowita, a na przykład 127.0.0.1 to tylko jedna z wielu (choć najczęstszych) reprezentacji tekstowych. Ten sam typowy adres IPv4 interfejsu sprzężenia zwrotnego można również przedstawić jako 0x7f000001 lub 127.1 (być może bardziej odpowiedni tutaj, aby powiedzieć, że jest to 1adres w sieci klasy 127.0 / 8 klasy A) lub 0177.0.1, lub inne kombinacje 1 do 4 liczb wyrażonych jako liczba ósemkowa, dziesiętna lub szesnastkowa. Możesz przekazać je wszystkim, pingna przykład, a zobaczysz, że wszystkie będą pingować localhost.
Jeśli nie przeszkadza ci efekt uboczny ustawiania dowolnej zmiennej tymczasowej (tutaj $n), w bashlub ksh93lub zsh -o octalzeroeslub lksh -o posix, możesz po prostu przekonwertować wszystkie te reprezentacje z powrotem na 32-bitową liczbę całkowitą za pomocą:
$((n=32,(${IP//./"<<(n-=8))+("})))
A następnie wyodrębnij wszystkie składniki za pomocą >>/ &kombinacji takich jak powyżej.
$ 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
mkshużywa 32-bitowych liczb całkowitych ze znakiem dla wyrażeń arytmetycznych, można $((# n=32,...))tam użyć , aby wymusić użycie 32-bitowych liczb bez znaku (i posixopcję rozpoznawania stałych ósemkowych).
IFSnareadtam:IFS=. read -a ArrIP<<<"$IP"