Ho il seguente modello in una stringa (un indirizzo IP):
123.444.888.235
Voglio sostituire l'ultimo numero dopo il punto con 0
, quindi diventa:
123.444.888.0
Come potrei farlo in bash
un altro linguaggio di script di shell?
Ho il seguente modello in una stringa (un indirizzo IP):
123.444.888.235
Voglio sostituire l'ultimo numero dopo il punto con 0
, quindi diventa:
123.444.888.0
Come potrei farlo in bash
un altro linguaggio di script di shell?
Risposte:
In qualsiasi shell POSIX:
var=123.444.888.235
new_var="${var%.*}.0"
${var%pattern}
è un operatore introdotto ksh
negli anni '80, standardizzato da POSIX per il sh
linguaggio standard e ora implementato da tutte le shell che interpretano quel linguaggio, incluso bash
.
${var%pattern}
si espande al contenuto di $var
stripped della stringa più corta che corrisponde al pattern alla fine di esso (o allo stesso modo in cui $var
tale pattern non corrisponde). Quindi ${var%.*}
(dove .*
è un modello che significa punto seguito da un numero qualsiasi di caratteri) si espande $var
senza il più a destra .
e cosa lo segue. Al contrario, ${var%%.*}
dove viene spogliata la stringa più lunga che corrisponde al modello si espanderebbe $var
senza quella più a sinistra .
e ciò che segue.
${var%.*}
man bash
e premere invio, quindi digitare /suffix pattern
e premere invio . :)
new_var="${var%.*}.0"
... nJoy !.
Alcuni modi (tutti presuppongono che si desideri modificare l'ultimo set di numeri nella stringa):
$ echo 123.444.888.235 | awk -F'.' -vOFS='.' '{$NF=0}1;'
123.444.888.0
Qui, -F'.'
dice awk
di usare .
come separatore del campo di input e -vOFS='.'
di usarlo come separatore del campo di output. Quindi, impostiamo semplicemente l'ultimo campo ( $NF
) su 0 e stampiamo la linea ( 1;
è la awk
scorciatoia per "stampare la linea corrente").
$ echo 123.444.888.235 | perl -pe 's/\d+$/0/'
123.444.888.0
La -p
dice perl
per stampare ogni linea di ingresso dopo l'applicazione dello script data dal -e
. Lo script stesso è solo un semplice operatore di sostituzione che sostituirà uno o più numeri alla fine della riga 0
.
$ echo 123.444.888.235 | sed 's/[0-9]*$/0/'
123.444.888.0
La stessa idea in sed
, usando [0-9]
invece di \d
.
Se la tua stringa è in una variabile e usi una shell che supporta stringhe qui (come bash
o zsh
per esempio), puoi cambiare quanto sopra in:
awk -F'.' -vOFS='.' '{$NF=0}1;' <<<$var
perl -pe 's/\d+$/0/' <<<$var
sed 's/[0-9]*$/0/' <<<$var
Dato che il tuo input è un indirizzo IP e che stai sostituendo l'ultimo ottetto di quell'indirizzo .0
, suppongo che ciò che stai veramente cercando di ottenere sia calcolare la porzione di rete dell'indirizzo IP, usando la 255.255.255.0
maschera di rete.
La semplice sostituzione di ottetti con zero è OK se la lunghezza della maschera di rete è divisibile per 8, ma non è questo il caso generale. Se hai mai bisogno di eseguire questa operazione per qualsiasi maschera di rete (sottorete) valida, puoi fare qualcosa del genere:
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
Questo definisce 3 funzioni:
d2i()
converte la forma decimale puntata di un indirizzo IP (o maschera) in un intero semplicei2d()
fa il contrario: converte un intero semplice in un decimale puntatoipmask()
calcola semplicemente un AND bit a bit di un indirizzo e una maschera di rete per fornire la porzione di rete di un indirizzo. Bash prevede che gli operandi &
siano numeri interi.Le due chiamate per ipmask
mostrare come la rete può essere calcolata da un indirizzo IP per due diverse maschere.
Nota come indicato nella domanda, 123.444.888.235
è un indirizzo IP non valido. Ho usato 123.44.88.235
invece per questi esempi.