web-dev-qa-db-fra.com

Supprimer les zéros de gauche avant de passer une variable Shell à une autre commande

Il s’avère que iptables ne gère pas très bien les zéros non significatifs. Comme $machinenumber doit être précédé d'un zéro initial à d'autres fins, il s'agit simplement de créer une nouvelle variable ($nozero) basée sur $machinenumber, où les zéros sont éliminés.

$machinenumber est un nombre à deux chiffres compris entre 01 et 24. Il est actuellement 09

$machinetype est 74 pour l'instant et n'a pas causé de problèmes auparavant.

Ce que j'ai jusqu'ici c'est:

nozero = (echo $machinenumber | sed 's/^0*//')
iptables -t nat -I POSTROUTING -s 10.($machinetype).($nozero).0/24 -j MASQUERADE

Bien que je pense être sur la bonne voie, le code se traduit par:

ERROR - Unknown string operation
33
Jarmund

Vous n'avez pas besoin d'utiliser sed ou un autre utilitaire externe. Voici quelques façons dont Bash peut supprimer les zéros non significatifs pour vous.

iptables -t nat -I POSTROUTING -s "10.$machinetype.$((10#$machinenumber)).0/24" -j MASQUERADE

$(()) définit un contexte arithmétique et le 10# convertit le nombre de base 10 en base 10, ce qui entraîne la suppression des zéros non significatifs.

shopt -s extglob
iptables -t nat -I POSTROUTING -s "10.$machinetype.${machinenumber##+(0)}.0/24" -j MASQUERADE

Lorsque extglob est activé, le développement de paramètre présenté supprime tous les zéros non significatifs. Malheureusement, si la valeur d'origine est 0, le résultat est une chaîne nulle.

48
Dennis Williamson

Non, vous corrigez tout (presque tous) correctement… .. Il vous suffit de:

  • supprimer les espaces autour de =
  • utilisez $() ou des backticks au lieu de ()

Ce serait correct:

 nozero=$(echo $machinenumber | sed 's/^0*//')

Aussi, vous devez utiliser des variables sans () autour d'elles. Vous pouvez ajouter "" si vous voulez:

iptables -t nat -I POSTROUTING -s "10.$machinetype.$nozero.0/24" -j MASQUERADE

Et bien sûr, les variables ici ne sont pas nécessaires. Vous pouvez dire simplement:

iptables -t nat -I POSTROUTING -s "10.$(echo $machinenumber | sed 's/^0*//').$nozero.0/24" -j MASQUERADE
21
Igor Chubin

tu peux aussi faire

machinenumber=$(expr $machinenumber + 0)
16
pizza

Je ne peux pas commenter car je n'ai pas assez de réputation, mais je suggérerais que vous acceptiez la réponse de Dennis (ce qui est vraiment très joli)

Premièrement, je ne pense pas que votre réponse soit valide bash . Dans mon installation, je reçois:

> machinetype=74
> machinenumber=05
> iptables -t nat -I POSTROUTING -s 10.($machinetype).($machinenumber + 0).0/24 -j MASQUERADE
-bash: syntax error near unexpected token `('
> echo 10.($machinetype).($machinenumber + 0).0/24
-bash: syntax error near unexpected token `('

Si je le cite je reçois:

> echo "($machinetype).($machinenumber + 0)"
(74).(05 + 0)

Je suppose que vous voulez dire:

> echo 10.$(($machinetype)).$(($machinenumber + 0)).0/24
10.74.5.0/24

Mais, bien sûr, c'est toujours une mauvaise solution à cause de l'octal:

> machinenumber=09
> echo 10.$(($machinetype)).$(($machinenumber + 0)).0/24
-bash: 09: value too great for base (error token is "09")

Je suppose que vos chiffres ne sont pas 08 ou 09 pour le moment.

Voici Dennis's:

> echo $((10#09))
9
> echo $((10#00))
0
> echo $((10#00005))
5
> echo $((10#))
0

Certes, ce dernier pourrait être un problème de validation d’entrée pour quelqu'un.

La solution sed a le problème de:

> echo "0" | sed 's/^0*//'

>
8
Duncan Irvine
nozero=$(echo $machinenumber | sed 's/^0*//')

Essayez sans espaces autour de = et avec un signe supplémentaire $.

6
Balint

Une solution pure bash:

> N=0001023450 
> [[ $N =~ "0*(.*)" ]] && N=${BASH_REMATCH[1]}
> echo $N 
1023450
5
user136623

Utilisation de sed:

echo 000498 | sed "s/^0*\([1-9]\)/\1/;s/^0*$/0/"
498
echo 000 | sed "s/^0*\([1-9]\)/\1/;s/^0*$/0/"
0
3
Jahid

Je le fais en utilisant 

awk '{print $1 + 0}'

J'aime mieux cette approche que sed car elle fonctionne toujours avec des nombres comme 0, 000 et 001.

Donc, dans votre exemple, je remplacerais 

nozero=$(echo $machinenumber | sed 's/^0*//')

avec 

nozero=$(echo $machinenumber | awk '{print $1 + 0}' )

Je ne peux pas non plus commenter ou voter, mais la réponse de Duncan Irvine est la meilleure.

J'aimerais ajouter une note sur la portabilité. La syntaxe $((10#0009)) n'est pas portable. Cela fonctionne en bash et en ksh, mais pas au tiret:

$ echo $((10#09))
dash: 1: arithmetic expression: expecting EOF: "10#09"

$ dpkg -s dash | grep -i version
Version: 0.5.7-2ubuntu2

Si la portabilité est importante pour vous, utilisez la réponse sed.

2
Aurelio Jargas

Je dirais que vous êtes très proche. Je ne vois pas d'exigence spécifiée pour bash, mais votre logique non nulle est imparfaite.

nonzero=`echo $machinenumber + 0 | bc`
iptables -t nat -I POSTROUTING -s 10.$machinetype.$nozero.0/24 -j MASQUERADE

L'ajout de 0 est une méthode courante pour changer un numéro de chaîne en un entier non complété. BC est une calculatrice de base. J'utilise cette méthode pour supprimer tout le temps l'espace et les zéros.

Bien que je ne sois pas expert en syntaxe iptables, je suis presque sûr que les parenthèses ne sont pas nécessaires. Comme j'ai déjà des caractères non-Word bordant les deux variables, je n'ai pas besoin de lettres spéciales autour d'eux. Les caractères de mot sont; 

[a-zA-z0-9_]

Avec cette solution, vous ne perdez pas la valeur zéro en tant que valeur potentielle et devez être portable dans tous les environnements.

1
Daniel Liston

Ajoutez le nombre avec 0, cela supprimera les zéros de gauche

eg: expr 00010 + 0 #becomes 10

OR

num=00076
num=${num##+(0)}
echo $num
0
Aashutosh

Si vous n'avez pas sed, awk ou Perl, vous pouvez utiliser cut et grep

mn="$machinenumber"
while echo "$mn"|grep -q '^0';do mn=$(echo "$mn"|cut -c2-);done
iptables -t nat -I POSTROUTING -s 10.($machinetype).($mn).0/24 -j MASQUERADE

Fonctionne avec les deux bash et dash shell.

0
Alexx Roche

Si vous utilisez bash, cela ressemble au plus simple:

nozero=$(bc<<<$machinenumber)
0
Cyker