50

事实证明,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
4

14 回答 14

76

您不需要使用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,则结​​果为空字符串。

于 2012-06-21T01:10:23.267 回答
24

不,您使所有(几乎所有)都正确。你必须:

  • 删除周围的空格=
  • 使用$()或反引号代替()

那将是正确的:

 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
于 2012-06-20T16:20:44.653 回答
22

你也可以

machinenumber=$(expr $machinenumber + 0)
于 2012-06-20T18:17:00.697 回答
10

我无法发表评论,因为我没有足够的声誉,但我建议你接受丹尼斯的回答(这真的很整洁)

首先,我认为您的答案不是有效的 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*//'

>
于 2013-08-21T15:33:49.727 回答
7
nozero=$(echo $machinenumber | sed 's/^0*//')

尝试在周围没有空格=并使用附加$标志。

于 2012-06-20T16:20:23.763 回答
6

一个纯粹的 bash 解决方案:

> N=0001023450 
> [[ $N =~ "0*(.*)" ]] && N=${BASH_REMATCH[1]}
> echo $N 
1023450
于 2013-10-23T18:05:03.173 回答
5

使用 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
于 2015-08-07T00:17:02.387 回答
3

我通过使用来做到这一点

awk '{print $1 + 0}'

我比 sed 方法更喜欢这种方法,因为它仍然适用于 0、000 和 001 等数字。

所以在你的例子中我会替换

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

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

于 2013-04-06T14:47:08.683 回答
2

我还不能评论或投票,但 Duncan Irvine 的回答是最好的。

我想添加一个关于可移植性的说明。$((10#0009))语法不可移植。它适用于 bash 和 ksh,但不适用于 dash:

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

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

如果可移植性对您很重要,请使用 sed 答案。

于 2015-02-11T12:34:29.233 回答
2

如果您使用的是 bash,这看起来是最简单的:

nozero=$(bc<<<$machinenumber)
于 2018-09-10T05:30:03.720 回答
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 移植。

于 2017-08-21T23:57:48.103 回答
1

添加数字与 0,它将删除前导零

eg: expr 00010 + 0 #becomes 10

或者

num=00076
num=${num##+(0)}
echo $num
于 2018-10-25T20:23:05.220 回答
0

前几天我不得不重新访问这段代码,因为一些不相关的东西,并且由于与其他一些读取相同脚本的软件的兼容性,我发现将它重写成这个很容易,它应该仍然是有效的 bash:

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

基本上,添加 0 会强制将其解释为整数,因此会自动去除前导零

于 2013-02-22T13:58:27.033 回答
0

如果您没有 sed 或 awk 或 perl,那么您可以使用cutgrep

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 shell。

于 2018-12-30T13:01:58.383 回答