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), bash4.3+, busybox sh, yash, mkshve zshtabii 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 $IPgüvenilmeyen bir kaynaktan gelmesi, komut enjeksiyon güvenlik açığı anlamına gelir.
Temel olarak, biz her değiştiriyorsanız olarak .yer $IPile +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. zshfarklı bir sözdizimi ile destekler:
$ setopt extendedglob # for (#b)
$ echo ${IP/(#b)(*).(*).(*).(*)/$match[2]}'
96
bashregexp 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")
noglobDeğerleri için kötü sürprizlerden kaçınmak için $IPbö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 1de 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), bashya ksh93da zsh -o octalzeroesya da ya da ayarlamanın yan etkisine dikkat lksh -o posixetmezseniz, 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
mksharitmetik 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 posixsekizli sabitleri tanıma seçeneği) zorlamak için kullanabilirsiniz .
IFSiçinread: oradaIFS=. read -a ArrIP<<<"$IP"