Saya memiliki pola berikut dalam string (alamat IP):
123.444.888.235
Saya ingin mengganti angka terakhir setelah titik dengan 0
, sehingga menjadi:
123.444.888.0
Bagaimana saya bisa melakukannya dalam bash
bahasa shell script lain?
Saya memiliki pola berikut dalam string (alamat IP):
123.444.888.235
Saya ingin mengganti angka terakhir setelah titik dengan 0
, sehingga menjadi:
123.444.888.0
Bagaimana saya bisa melakukannya dalam bash
bahasa shell script lain?
Jawaban:
Dalam setiap shell POSIX:
var=123.444.888.235
new_var="${var%.*}.0"
${var%pattern}
adalah operator yang diperkenalkan oleh ksh
pada tahun 80an, distandarisasi oleh POSIX untuk sh
bahasa standar dan sekarang diimplementasikan oleh semua shell yang menafsirkan bahasa itu, termasuk bash
.
${var%pattern}
memperluas ke konten $var
dilucuti dari string terpendek yang cocok dengan pola dari ujungnya (atau sama seperti $var
jika pola itu tidak cocok). Jadi ${var%.*}
(di mana .*
merupakan pola yang berarti dot diikuti oleh sejumlah karakter) memperluas ke $var
tanpa-paling tepat .
dan apa yang mengikutinya. Sebaliknya, di ${var%%.*}
mana string terpanjang yang cocok dengan pola dilucuti akan diperluas ke $var
tanpa yang paling kiri .
dan apa yang mengikutinya.
${var%.*}
man bash
dan tekan enter, lalu ketik /suffix pattern
dan tekan enter. :)
new_var="${var%.*}.0"
... nJoy !.
Beberapa cara (ini semua mengasumsikan bahwa Anda ingin mengubah set angka terakhir dalam string):
$ echo 123.444.888.235 | awk -F'.' -vOFS='.' '{$NF=0}1;'
123.444.888.0
Di sini, -F'.'
diperintahkan awk
untuk digunakan .
sebagai pemisah bidang input dan -vOFS='.'
menggunakannya sebagai pemisah bidang keluaran. Kemudian, kami hanya mengatur bidang terakhir ( $NF
) ke 0 dan mencetak garis ( 1;
adalah awk
singkatan untuk "mencetak baris saat ini").
$ echo 123.444.888.235 | perl -pe 's/\d+$/0/'
123.444.888.0
The -p
memberitahu perl
untuk mencetak setiap baris masukan setelah menerapkan script yang diberikan oleh -e
. Script itu sendiri hanyalah operator substitusi sederhana yang akan menggantikan satu atau lebih angka di akhir baris 0
.
$ echo 123.444.888.235 | sed 's/[0-9]*$/0/'
123.444.888.0
Gagasan yang sama sed
, menggunakan [0-9]
alih-alih \d
.
Jika string Anda dalam variabel dan Anda menggunakan shell yang mendukung string di sini (seperti bash
atau zsh
misalnya), Anda dapat mengubah hal di atas menjadi:
awk -F'.' -vOFS='.' '{$NF=0}1;' <<<$var
perl -pe 's/\d+$/0/' <<<$var
sed 's/[0-9]*$/0/' <<<$var
Karena input Anda adalah alamat IP, dan Anda mengganti oktet terakhir dari alamat itu .0
, maka saya berasumsi apa yang benar - benar ingin Anda capai adalah menghitung bagian jaringan dari alamat IP, menggunakan 255.255.255.0
netmask.
Mengganti oktet dengan nol tidak masalah jika panjang netmask Anda dapat dibagi 8, tetapi ini bukan kasus umum. Jika Anda perlu melakukan operasi ini untuk netmask (subnet) yang valid, maka Anda dapat melakukan sesuatu seperti ini:
function d2i() {
echo $(( 0x$( printf "%02x" ${1//./ } ) ))
}
function i2d() {
h=$( printf "%08X" "$1" )
echo $(( 0x${h:0:2} )).$(( 0x${h:2:2} )).$(( 0x${h:4:2} )).$(( 0x${h:6:2} ))
}
function ipmask() {
i2d $(( $( d2i $1 ) & $( d2i $2 ) ))
}
ipmask 123.44.88.235 255.255.255.0 # outputs 123.44.88.0
ipmask 123.44.88.235 255.255.255.240 # outputs 123.44.88.224
Ini mendefinisikan 3 fungsi:
d2i()
mengubah bentuk desimal bertitik dari alamat IP (atau mask) menjadi integer sederhanai2d()
melakukan yang sebaliknya - mengonversi bilangan bulat sederhana ke desimal bertitikipmask()
hanya menghitung bitwise AND dari alamat dan netmask untuk memberikan bagian jaringan dari alamat. Bash mengharapkan operan &
menjadi bilangan bulat.Dua panggilan untuk ipmask
menunjukkan bagaimana jaringan dapat dihitung dari alamat IP untuk dua topeng yang berbeda.
Catatan seperti yang dinyatakan dalam pertanyaan, 123.444.888.235
adalah alamat IP yang tidak valid. 123.44.88.235
Sebagai gantinya saya menggunakan contoh-contoh ini.