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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 22:16:59  来源:igfitidea点击:

Removing leading zeros before passing a shell variable to another command

bashstrip

提问by Jarmund

It turns out that iptables doesn't handle leading zeros too well. As $machinenumberthat 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,其中去除了前导零。

$machinenumberis a two-digit number between 01 and 24. Currently it's 09

$machinenumber是 01 到 24 之间的两位数。目前是 09

$machinetypeis 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 sedor 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 extglobis 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 中移植。