Removing leading zeros before passing a shell variable to another command
It turns out that iptables doesn't handle leading zeros too well. As $machinenumber
that is used has to have a leading zero in it for other purposes, the idea is simply to create a new variable ($nozero
) based on $machinenumber
, where leading zeros are stripped away.
$machinenumber
is a two-digit number between 01 and 24. Currently it's 09
$machinetype
is 74 for now and hasn't caused any problems before.
What I have so far is:
nozero = (echo $machinenumber | sed 's/^0*//')
iptables -t nat -I POSTROUTING -s 10.($machinetype).($nozero).0/24 -j MASQUERADE
While I believe I'm on the right track, the code results in:
ERROR - Unknown string operation
Solution 1:
You don't need to use sed
or another external utility. Here are a couple of ways Bash can strip the leading zeros for you.
iptables -t nat -I POSTROUTING -s "10.$machinetype.$((10#$machinenumber)).0/24" -j MASQUERADE
The $(())
sets up an arithmetic context and the 10#
converts the number from base 10 to base 10 causing any leading zeros to be dropped.
shopt -s extglob
iptables -t nat -I POSTROUTING -s "10.$machinetype.${machinenumber##+(0)}.0/24" -j MASQUERADE
When extglob
is turned on, the parameter expansion shown removes all leading zeros. Unfortunately, if the original value is 0, the result is a null string.
Solution 2:
No, you make all (alomost all) correct. You just must:
- remove spaces around
=
- use
$()
or backticks instead of()
That would be correct:
nozero=$(echo $machinenumber | sed 's/^0*//')
Also you must use variables without ()
around them. You can add ""
if you want:
iptables -t nat -I POSTROUTING -s "10.$machinetype.$nozero.0/24" -j MASQUERADE
And of course variables here are not necessary. You can say simply:
iptables -t nat -I POSTROUTING -s "10.$(echo $machinenumber | sed 's/^0*//').$nozero.0/24" -j MASQUERADE
Solution 3:
you can also do
machinenumber=$(expr $machinenumber + 0)
Solution 4:
I can't comment as I don't have sufficient reputation, but I would suggest you accept Dennis's answer (which is really quite neat)
Firstly, I don't think that your answer is valid bash. In my install I get:
> 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 `('
If I quote it I get:
> echo "($machinetype).($machinenumber + 0)"
(74).(05 + 0)
I'm assuming you mean:
> echo 10.$(($machinetype)).$(($machinenumber + 0)).0/24
10.74.5.0/24
But, of course it's still a bad solution because of octal:
> machinenumber=09
> echo 10.$(($machinetype)).$(($machinenumber + 0)).0/24
-bash: 09: value too great for base (error token is "09")
I assume that your numbers aren't 08 or 09 at the moment.
Here's Dennis's:
> echo $((10#09))
9
> echo $((10#00))
0
> echo $((10#00005))
5
> echo $((10#))
0
Admittedly, that last one might be an input validation problem for someone.
The sed solution has the problem of:
> echo "0" | sed 's/^0*//'
>
Solution 5:
nozero=$(echo $machinenumber | sed 's/^0*//')
Try without the spaces around =
and with an additional $
sign.