bash 在将 shell 变量传递给另一个命令之前删除前导零
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11123717/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Removing leading zeros before passing a shell variable to another command
提问by Jarmund
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.
事实证明,iptables 不能很好地处理前导零。由于$machinenumber
用于其他目的必须在其中包含前导零,因此该想法只是创建一个$nozero
基于的新变量 ( ) $machinenumber
,其中去除了前导零。
$machinenumber
is a two-digit number between 01 and 24. Currently it's 09
$machinenumber
是 01 到 24 之间的两位数。目前是 09
$machinetype
is 74 for now and hasn't caused any problems before.
$machinetype
现在是 74,之前没有造成任何问题。
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
采纳答案by Jarmund
I had to revisit this code the other day due to some unrelated stuff, and due to compatibility with some other software that reads the same script, i found it a lot easiest to rewrite it into this, which should still be valid bash:
由于一些不相关的东西,我不得不在前几天重新访问这段代码,并且由于与读取相同脚本的其他一些软件的兼容性,我发现将它重写成这个很容易,它应该仍然是有效的 bash:
iptables -t nat -I POSTROUTING -s 10.($machinetype).($machinenumber + 0).0/24 -j MASQUERADE
iptables -t nat -I POSTROUTING -s 10.($machinetype).($machinenumber + 0).0/24 -j MASQUERADE
Basically, adding 0 forces it to be interpreted as an integer, hence automatically stripping the leading zeros
基本上,添加 0 会强制将其解释为整数,因此会自动去除前导零
回答by Paused until further notice.
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.
您不需要使用sed
或其他外部实用程序。以下是 Bash 可以为您去除前导零的几种方法。
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.
在$(())
设置了一个算术上下文和10#
被丢弃将从基座10的数量为10进制引起任何前导零。
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.
当extglob
被接通时,所述参数扩展示出移除了所有前导零。不幸的是,如果原始值为 0,则结果为空字符串。
回答by Igor Chubin
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
回答by pizza
you can also do
你也可以这样做
machinenumber=$(expr $machinenumber + 0)
回答by Duncan Irvine
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:
首先,我不认为你的回答是有效的 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 `('
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.
我假设您的号码目前不是 08 或 09。
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:
sed解决方案存在的问题是:
> echo "0" | sed 's/^0*//'
>
回答by Balint
nozero=$(echo $machinenumber | sed 's/^0*//')
Try without the spaces around =
and with an additional $
sign.
尝试没有周围的空间=
和附加$
标志。
回答by user136623
A pure bash solution:
一个纯粹的 bash 解决方案:
> N=0001023450
> [[ $N =~ "0*(.*)" ]] && N=${BASH_REMATCH[1]}
> echo $N
1023450
回答by Jahid
Using sed:
使用 sed:
echo 000498 | sed "s/^0*\([1-9]\)//;s/^0*$/0/"
498
echo 000 | sed "s/^0*\([1-9]\)//;s/^0*$/0/"
0
回答by Cullen Fluffy Jennings
I do it by using
我通过使用来做到这一点
awk '{print + 0}'
I like this better than the sed approach as it still works with numbers like 0, 000, and 001.
我比 sed 方法更喜欢这个方法,因为它仍然适用于 0、000 和 001 等数字。
So in your example I would replace
所以在你的例子中,我会替换
nozero=$(echo $machinenumber | sed 's/^0*//')
with
和
nozero=$(echo $machinenumber | awk '{print + 0}' )
回答by Aurelio Jargas
I also can't comment or vote up yet, but the Duncan Irvine answer is the best.
我还不能发表评论或投票,但邓肯欧文的答案是最好的。
I'd like to add a note about portability. The $((10#0009))
syntax is not portable. It works in bash and ksh, but not in dash:
我想添加一个关于便携性的说明。该$((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
If portability is important to you, use the sed answer.
如果可移植性对您很重要,请使用 sed 答案。
回答by Daniel Liston
I would say you are very close. I do not see a requirement stated for bash, but your nonzero logic is flawed.
我会说你非常接近。我没有看到针对 bash 的要求,但是您的非零逻辑有缺陷。
nonzero=`echo $machinenumber + 0 | bc`
iptables -t nat -I POSTROUTING -s 10.$machinetype.$nozero.0/24 -j MASQUERADE
Adding 0 is a common method for changing a string number into a non-padded integer. bc is a basic calculator. I use this method for removing space and zero padding from numbers all the time.
添加 0 是将字符串数字更改为非填充整数的常用方法。bc 是一个基本的计算器。我一直使用这种方法从数字中删除空格和零填充。
While I am not expert in iptables syntax, I am pretty sure the parenthesis are not necessary. Since I already have non-word characters bordering both variables, I do not need special enclosures around them. Word characters are;
虽然我不是 iptables 语法方面的专家,但我很确定括号不是必需的。因为我已经有非单词字符与两个变量接壤,所以我不需要在它们周围加上特殊的外壳。单词字符是;
[a-zA-z0-9_]
Using this solution, you do not lose zero as a potential value, and should be portable across all shells.
使用此解决方案,您不会丢失零作为潜在值,并且应该可以在所有 shell 中移植。