En kolay değil , ancak şöyle bir şey yapabilirsiniz:
$ 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
(Yani bu noktada ksh93 içinde çalışması gerekir ${var//pattern/replacement}
operatör gelir), bash
4.3+, busybox sh
, yash
, mksh
ve zsh
tabii gerçi de zsh
, çok daha basit yaklaşım vardır . Eski sürümlerinde bash
, iç tırnakları kaldırmanız gerekir. Diğer kabuklarda da kaldırılan bu iç tırnaklarla çalışır, ancak ksh93 ile çalışmaz.
Bu varsayım $IP
, bir IPv4 adresinin geçerli bir dört ondalık gösterimini içerir (ancak bu, aynı zamanda 0x6d.0x60.0x4d.0xf
(hatta bazı kabuklarda sekizlik) gibi dörtlü onaltılık gösterimler için de işe yarar, ancak değerleri ondalık olarak çıktılar). İçeriğinin $IP
güvenilmeyen bir kaynaktan gelmesi, komut enjeksiyon güvenlik açığı anlamına gelir.
Temel olarak, biz her değiştiriyorsanız olarak .
yer $IP
ile +256*(
biz değerlendirerek sonunda:
$(( (109+256*(96+256*(77+256*(15))))>> x &255 ))
Biz bir IPv4 adresi gibi bu 4 bayt dışında 32 bitlik tamsayı inşa ediyoruz Yani sonuçta (bayt ters olsa birlikte) 'dir ¹ ve daha sonra kullanarak >>
, &
ilgili bayt ayıklamak için bitsel operatörleri.
Aksi takdirde aritmetik ayrıştırıcı eşleşmeyen parantezden şikayetçi olacağı için ${param+value}
standart operatörü (burada $-
her zaman ayarlanması garanti edilen) kullanırız value
. Buradaki kabuk ))
, açıklığın kapanışını bulabilir $((
ve daha sonra değerlendirilecek aritmetik ifadeye neden olacak şekilde genişletmeleri gerçekleştirebilir.
Bunun $(((${IP//./"+256*("}))))&255))
yerine, kabuk )
orada ikinci ve üçüncü s'yi kapanış ))
olarak ele alır $((
ve bir sözdizimi hatası bildirir.
Ksh93'te şunları da yapabilirsiniz:
$ echo "${IP/@(*).@(*).@(*).@(*)/\2}"
96
bash
, mksh
, zsh
Ksh93 en kopyaladığınız ${var/pattern/replacement}
operatörü ama Yakalama-grup kısmını ele değil. zsh
farklı bir sözdizimi ile destekler:
$ setopt extendedglob # for (#b)
$ echo ${IP/(#b)(*).(*).(*).(*)/$match[2]}'
96
bash
regexp eşleştirme işlecinde bir tür yakalama grubu işlemeyi destekliyor , ancak içeri almıyor ${var/pattern/replacement}
.
POSIXly, şunu kullanırsınız:
(IFS=.; set -o noglob; set -- $IP; printf '%s\n' "$2")
noglob
Değerleri için kötü sürprizlerden kaçınmak için $IP
böyle 10.*.*.*
altkabuk seçenekleri ve söz konusu değişikliklerin kapsamını sınırlamak için, $IFS
.
IP IPv4 adresi yalnızca 32 bit tam sayıdır ve örneğin 127.0.0.1 (en yaygın olsa da) metinsel gösterimlerden yalnızca biridir. Geridöngü arabiriminin aynı tipik IPv4 adresi 0x7f000001 veya 127.1 (belki 1
de 127.0 / 8 sınıf A ağındaki adres olduğunu söylemek için daha uygun bir adres) veya 0177.0.1 veya 1'in diğer kombinasyonları olarak temsil edilebilir. sekizlik, ondalık veya onaltılı olarak ifade edilen 4 sayıya kadar. Bunların tümünü ping
örneğin aktarabilirsiniz ve hepsinin yerel ana bilgisayara ping atacağını görürsünüz.
İsterseniz geçici bir değişken (burada $n
), bash
ya ksh93
da zsh -o octalzeroes
ya da ya da ayarlamanın yan etkisine dikkat lksh -o posix
etmezseniz, tüm bu gösterimleri aşağıdaki şekilde 32 bit tam sayıya dönüştürebilirsiniz:
$((n=32,(${IP//./"<<(n-=8))+("})))
Ve sonra yukarıdaki gibi >>
/ &
kombinasyonları ile tüm bileşenleri çıkarın .
$ 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
aritmetik ifadeleri için imzalı 32 bit tamsayıları kullanırsa, $((# n=32,...))
burada imzasız 32 bit sayılarının kullanımını (ve posix
sekizli sabitleri tanıma seçeneği) zorlamak için kullanabilirsiniz .
IFS
içinread
: oradaIFS=. read -a ArrIP<<<"$IP"