J'ai le modèle suivant dans une chaîne (une adresse IP):
123.444.888.235
Je veux remplacer le dernier numéro après le point par 0
, il devient donc:
123.444.888.0
Comment pourrais-je le faire dans bash
un autre langage de script shell?
J'ai le modèle suivant dans une chaîne (une adresse IP):
123.444.888.235
Je veux remplacer le dernier numéro après le point par 0
, il devient donc:
123.444.888.0
Comment pourrais-je le faire dans bash
un autre langage de script shell?
Réponses:
Dans n'importe quel shell POSIX:
var=123.444.888.235
new_var="${var%.*}.0"
${var%pattern}
est un opérateur introduit par ksh
dans les années 80, normalisé par POSIX pour le sh
langage standard et maintenant implémenté par tous les shells qui interprètent ce langage, notamment bash
.
${var%pattern}
se développe au contenu de $var
dépouillé de la chaîne la plus courte qui correspond au modèle à la fin de celui-ci (ou au même que $var
si ce modèle ne correspond pas). Donc ${var%.*}
(où .*
est un motif qui signifie un point suivi d'un nombre quelconque de caractères) se développe $var
sans le plus à droite .
et ce qui le suit. En revanche, ${var%%.*}
là où la chaîne la plus longue qui correspond au modèle est supprimée, elle se développerait $var
sans le plus à gauche .
et ce qui suit.
${var%.*}
man bash
et appuyez sur entrée, puis tapez /suffix pattern
et appuyez sur entrée. :)
new_var="${var%.*}.0"
... nJoy !.
Quelques façons (elles supposent toutes que vous souhaitez modifier le dernier ensemble de nombres de la chaîne):
$ echo 123.444.888.235 | awk -F'.' -vOFS='.' '{$NF=0}1;'
123.444.888.0
Ici, -F'.'
indique awk
d'utiliser .
comme séparateur de champ d'entrée et -vOFS='.'
de l'utiliser comme séparateur de champ de sortie. Ensuite, nous mettons simplement le dernier champ ( $NF
) à 0 et imprimons la ligne ( 1;
est un awk
raccourci pour "imprimer la ligne actuelle").
$ echo 123.444.888.235 | perl -pe 's/\d+$/0/'
123.444.888.0
Le -p
dit perl
d'imprimer chaque ligne d'entrée après avoir appliqué le script donné par -e
. Le script lui-même n'est qu'un simple opérateur de substitution qui remplacera un ou plusieurs nombres à la fin de la ligne par 0
.
$ echo 123.444.888.235 | sed 's/[0-9]*$/0/'
123.444.888.0
La même idée dans sed
, en utilisant [0-9]
au lieu de \d
.
Si votre chaîne est dans une variable et que vous utilisez un shell qui prend en charge ici les chaînes (telles que bash
ou zsh
par exemple), vous pouvez changer ce qui précède en:
awk -F'.' -vOFS='.' '{$NF=0}1;' <<<$var
perl -pe 's/\d+$/0/' <<<$var
sed 's/[0-9]*$/0/' <<<$var
Étant donné que votre entrée est une adresse IP et que vous remplacez le dernier octet de cette adresse .0
, je suppose que ce que vous essayez vraiment de réaliser est de calculer la partie réseau de l'adresse IP à l'aide du 255.255.255.0
masque de réseau.
Remplacer simplement des octets par des zéros est OK si la longueur de votre masque de réseau est divisible par 8, mais ce n'est pas le cas général. Si vous devez effectuer cette opération pour n'importe quel masque de sous-réseau valide (sous-réseau), vous pouvez faire quelque chose comme ceci:
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
Cela définit 3 fonctions:
d2i()
convertit la forme décimale en pointillés d'une adresse IP (ou d'un masque) en un entier simplei2d()
fait le contraire - convertit un entier simple en une décimale en pointillésipmask()
calcule simplement un ET au niveau du bit d'une adresse et d'un masque de réseau pour donner la partie réseau d'une adresse. Bash s'attend à ce que les opérandes de &
soient des entiers.Les deux appels ipmask
montrent comment le réseau peut être calculé à partir d'une adresse IP pour deux masques différents.
Remarque, comme indiqué dans la question, 123.444.888.235
est une adresse IP non valide. J'ai utilisé à la 123.44.88.235
place pour ces exemples.