事实证明,iptables不能很好地处理前导零。由于使用的$machinenumber
必须在其中具有前导零以用于其他目的,因此想法只是基于$nozero
创建一个新变量($machinenumber
),其中前导零被剥离程。
$machinenumber
是01到24之间的两位数字。目前它是09
$machinetype
现在是74,并且之前没有造成任何问题。
到目前为止我所拥有的是:
nozero = (echo $machinenumber | sed 's/^0*//')
iptables -t nat -I POSTROUTING -s 10.($machinetype).($nozero).0/24 -j MASQUERADE
虽然我相信自己走在了正确的轨道上,但代码的结果是:
ERROR - Unknown string operation
答案 0 :(得分:50)
您无需使用sed
或其他外部实用程序。以下两种方式Bash可以为您删除前导零。
iptables -t nat -I POSTROUTING -s "10.$machinetype.$((10#$machinenumber)).0/24" -j MASQUERADE
$(())
设置算术上下文,10#
将数字从基数10转换为基数10,导致任何前导零被删除。
shopt -s extglob
iptables -t nat -I POSTROUTING -s "10.$machinetype.${machinenumber##+(0)}.0/24" -j MASQUERADE
启用extglob
后,显示的参数展开会删除所有前导零。不幸的是,如果原始值为0,则结果为空字符串。
答案 1 :(得分:21)
不,你让所有(alomost all)正确。 你必须:
=
$()
或反引号代替()
这是正确的:
nozero=$(echo $machinenumber | sed 's/^0*//')
此外,您必须使用不带()
的变量。如果您愿意,可以添加""
:
iptables -t nat -I POSTROUTING -s "10.$machinetype.$nozero.0/24" -j MASQUERADE
当然,这里的变量不是必需的。你可以简单地说:
iptables -t nat -I POSTROUTING -s "10.$(echo $machinenumber | sed 's/^0*//').$nozero.0/24" -j MASQUERADE
答案 2 :(得分:16)
你也可以
machinenumber=$(expr $machinenumber + 0)
答案 3 :(得分:8)
我无法评论,因为我没有足够的声誉,但我建议你接受Dennis's answer(这真的很整洁)
首先,我不认为你的答案是有效的bash。 在我的安装中,我得到:
> 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 `('
如果我引用它,我会得到:
> echo "($machinetype).($machinenumber + 0)"
(74).(05 + 0)
我假设你的意思是:
> echo 10.$(($machinetype)).$(($machinenumber + 0)).0/24
10.74.5.0/24
但是,当然,由于八进制,它仍然是一个糟糕的解决方案:
> machinenumber=09
> echo 10.$(($machinetype)).$(($machinenumber + 0)).0/24
-bash: 09: value too great for base (error token is "09")
我认为你的号码目前不是08或09。
这是丹尼斯的:
> echo $((10#09))
9
> echo $((10#00))
0
> echo $((10#00005))
5
> echo $((10#))
0
不可否认,最后一个可能是某人的输入验证问题。
sed解决方案存在以下问题:
> echo "0" | sed 's/^0*//'
>
答案 4 :(得分:6)
nozero=$(echo $machinenumber | sed 's/^0*//')
尝试不使用=
周围的空格并使用额外的$
符号。
答案 5 :(得分:5)
纯粹的bash解决方案:
> N=0001023450
> [[ $N =~ "0*(.*)" ]] && N=${BASH_REMATCH[1]}
> echo $N
1023450
答案 6 :(得分:4)
使用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
答案 7 :(得分:3)
我是通过使用
来做到的awk '{print $1 + 0}'
我比sed方法更喜欢这个,因为它仍适用于0,000和001等数字。
所以在你的例子中我会替换
nozero=$(echo $machinenumber | sed 's/^0*//')
带
nozero=$(echo $machinenumber | awk '{print $1 + 0}' )
答案 8 :(得分:2)
我也无法评论或投票,但Duncan Irvine的答案是最好的。
我想添加一个关于可移植性的说明。 $((10#0009))
语法不可移植。它适用于bash和ksh,但不适用于破折号:
$ echo $((10#09))
dash: 1: arithmetic expression: expecting EOF: "10#09"
$ dpkg -s dash | grep -i version
Version: 0.5.7-2ubuntu2
如果可移植性对您很重要,请使用sed答案。
答案 9 :(得分:1)
我会说你很亲密。我没有看到针对bash的要求,但你的非零逻辑是有缺陷的。
nonzero=`echo $machinenumber + 0 | bc`
iptables -t nat -I POSTROUTING -s 10.$machinetype.$nozero.0/24 -j MASQUERADE
添加0是将字符串编号更改为非填充整数的常用方法。 bc是一个基本的计算器。我使用这种方法一直从数字中删除空格和零填充。
虽然我不是iptables语法方面的专家,但我很确定括号不是必需的。因为我已经有两个变量边界的非单词字符,所以我不需要在它们周围使用特殊的外壳。单词字符是;
[a-zA-z0-9_]
使用此解决方案,您不会将零作为潜在值丢失,并且应该可以在所有shell中移植。
答案 10 :(得分:1)
如果您正在使用bash,这看起来是最简单的:
nozero=$(bc<<<$machinenumber)
答案 11 :(得分:0)
由于一些不相关的东西,前几天我不得不重新访问这段代码,并且由于与其他一些读同一个脚本的软件的兼容性,我发现把它重写成这个很容易,这应该仍然是有效的bash :
iptables -t nat -I POSTROUTING -s 10.($machinetype).($machinenumber + 0).0/24 -j MASQUERADE
基本上,添加0会强制它被解释为整数,因此会自动剥离前导零
答案 12 :(得分:0)
将数字加0,将删除前导零
eg: expr 00010 + 0 #becomes 10
OR
num=00076
num=${num##+(0)}
echo $num
答案 13 :(得分:0)
如果您没有sed,awk或perl,则可以使用 cut 和 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
可与bash和dash外壳一起使用。
答案 14 :(得分:-4)
在bash中最简单:
%> a=00123
%> b=${a//0/}
b的值现在是“123”。
一般表格为${varname//find/replace}
,它会替换find
的任意数量的出现次数。