Bukan yang termudah , tetapi Anda dapat melakukan sesuatu seperti:
$ 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
Yang harus bekerja di ksh93 (mana yang ${var//pattern/replacement}Operator berasal dari), bash4.3+, busybox sh, yash, mkshdan zsh, meskipun tentu saja di zsh, ada pendekatan lebih sederhana . Di versi yang lebih lama bash, Anda harus menghapus kutipan dalam. Ini bekerja dengan kutipan batin yang dihapus di sebagian besar kerang lain juga, tetapi tidak ksh93.
Asumsi itu $IPberisi representasi quad-desimal valid dari alamat IPv4 (meskipun itu juga akan berfungsi untuk representasi quad-hexadecimal seperti 0x6d.0x60.0x4d.0xf(dan bahkan oktal dalam beberapa shell) tetapi akan menampilkan nilai dalam desimal). Jika konten $IPberasal dari sumber yang tidak dipercaya, itu akan berarti kerentanan injeksi perintah.
Pada dasarnya, seperti yang kita mengganti setiap .di $IPdengan +256*(, kita akhirnya mengevaluasi:
$(( (109+256*(96+256*(77+256*(15))))>> x &255 ))
Jadi kita membangun integer 32 bit dari 4 byte seperti alamat IPv4 pada akhirnya adalah (meskipun dengan byte terbalik)) dan kemudian menggunakan >>, &operator bitwise untuk mengekstrak byte yang relevan.
Kami menggunakan ${param+value}operator standar (di sini $-yang dijamin akan selalu ditetapkan) alih-alih hanya valuekarena parser aritmatika akan mengeluh tentang kurung yang tidak cocok. Shell di sini dapat menemukan penutup ))untuk pembukaan $((, dan kemudian melakukan ekspansi di dalam yang akan menghasilkan ekspresi aritmatika untuk dievaluasi.
Dengan $(((${IP//./"+256*("}))))&255))gantinya, shell akan memperlakukan kedua dan ketiga )s ada sebagai penutup ))untuk $((dan melaporkan kesalahan sintaks.
Di ksh93, Anda juga dapat melakukan:
$ echo "${IP/@(*).@(*).@(*).@(*)/\2}"
96
bash, mksh, zsh Telah menyalin ksh93 ini ${var/pattern/replacement}Operator tapi tidak yang menangkap-kelompok penanganan bagian. zshmendukungnya dengan sintaks yang berbeda:
$ setopt extendedglob # for (#b)
$ echo ${IP/(#b)(*).(*).(*).(*)/$match[2]}'
96
bashmendukung beberapa bentuk penanganan grup tangkap di operator pencocokan regexp , tetapi tidak dalam ${var/pattern/replacement}.
POSIXly, Anda akan menggunakan:
(IFS=.; set -o noglob; set -- $IP; printf '%s\n' "$2")
Untuk noglobmenghindari kejutan buruk untuk nilai $IPsuka 10.*.*.*, subkulit untuk membatasi ruang lingkup perubahan tersebut ke opsi dan $IFS.
¹ Alamat IPv4 hanya integer 32 bit dan 127.0.0.1 misalnya hanyalah salah satu dari banyak (meskipun yang paling umum) representasi tekstual. Alamat IPv4 tipikal yang sama dari antarmuka loopback juga dapat direpresentasikan sebagai 0x7f000001 atau 127.1 (mungkin yang lebih tepat di sini adalah 1alamat pada jaringan 127.0 / 8 kelas A), atau 0177.0.1, atau kombinasi lain dari 1 ke 4 angka yang dinyatakan sebagai oktal, desimal atau heksadesimal. Anda dapat mengirimkan semua itu pingmisalnya dan Anda akan melihat mereka semua melakukan ping localhost.
Jika Anda tidak keberatan efek samping menetapkan variabel sementara sewenang-wenang (di sini $n), di bashatau ksh93atau zsh -o octalzeroesatau lksh -o posix, Anda dapat mengkonversi semua representasi mereka kembali ke integer 32 bit dengan:
$((n=32,(${IP//./"<<(n-=8))+("})))
Lalu ekstrak semua komponen dengan >>/ &kombinasi seperti di atas.
$ 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
mkshmenggunakan bilangan bulat 32 bit yang ditandatangani untuk ekspresi aritmatika, Anda dapat menggunakannya di $((# n=32,...))sana untuk memaksa penggunaan angka 32 bit yang tidak ditandatangani (dan posixopsi untuknya mengenali konstanta oktal).
IFSuntuk direadsana:IFS=. read -a ArrIP<<<"$IP"