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 bashun 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 bashun 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 kshnegli anni '80, standardizzato da POSIX per il shlinguaggio standard e ora implementato da tutte le shell che interpretano quel linguaggio, incluso bash.
${var%pattern}si espande al contenuto di $varstripped della stringa più corta che corrisponde al pattern alla fine di esso (o allo stesso modo in cui $vartale pattern non corrisponde). Quindi ${var%.*}(dove .*è un modello che significa punto seguito da un numero qualsiasi di caratteri) si espande $varsenza il più a destra .e cosa lo segue. Al contrario, ${var%%.*}dove viene spogliata la stringa più lunga che corrisponde al modello si espanderebbe $varsenza quella più a sinistra .e ciò che segue.
${var%.*}
man bashe premere invio, quindi digitare /suffix patterne 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 awkdi 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 awkscorciatoia per "stampare la linea corrente").
$ echo 123.444.888.235 | perl -pe 's/\d+$/0/'
123.444.888.0
La -pdice perlper 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 basho zshper 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.0maschera 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 ipmaskmostrare 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.235invece per questi esempi.