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 bashun 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 bashun 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 kshdans les années 80, normalisé par POSIX pour le shlangage standard et maintenant implémenté par tous les shells qui interprètent ce langage, notamment bash.
${var%pattern}se développe au contenu de $vardépouillé de la chaîne la plus courte qui correspond au modèle à la fin de celui-ci (ou au même que $varsi 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 $varsans 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 $varsans le plus à gauche .et ce qui suit.
${var%.*}
man bashet appuyez sur entrée, puis tapez /suffix patternet 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 awkd'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 awkraccourci pour "imprimer la ligne actuelle").
$ echo 123.444.888.235 | perl -pe 's/\d+$/0/'
123.444.888.0
Le -pdit perld'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 bashou zshpar 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.0masque 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 ipmaskmontrent 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.235est une adresse IP non valide. J'ai utilisé à la 123.44.88.235place pour ces exemples.