11

我知道解决这个问题的其他方法确实有效(我目前正在使用'expr'方法),但它让我感到困扰,我无法弄清楚如何仅使用 bash 内置函数来解决这个问题。

当我尝试使用 ${variable##remove} 构造从变量中删除前导零时,我只能让它删除一个零或所有数字。

string="00123456"
echo "${string##0}" // Only the first 0 is removed
echo "${string##0*0}" // The whole string is removed
echo "${string#0*0}" // Works

string="01230"
echo "${string##0}" // Works
echo "${string##0*0}" // The whole string is removed
echo "${string#0*0}" // Again, the whole string is removed

我阅读了 bash 手册两次,看看我是否做得正确,但官方文档充其量是稀疏的。我知道启用 extglob 也可以解决这个问题,但对于像这样简单的问题来说,这似乎有点矫枉过正。

我是否遗漏了一些明显的东西,或者仅使用 bash 函数从字符串中删除一个或多个前导零真的很难吗?

4

5 回答 5

21

以下将从0字符串中删除所有前导 s:

$ string="000123456000"
$ echo "${string#"${string%%[!0]*}"}"
123456000

Saying"${string%%[!0]*}"将在删除满足的字符串的最长尾随部分后返回匹配项[!0]*——本质上是在开头返回零。

"${string#"${string%%[!0]*}"}"将从字符串的开头删除上面返回的部分。


或者,您可以使用 shell 算术:

$ string="0000123456000"
$ echo $((10#$string))
123456000
于 2013-11-08T14:40:27.813 回答
7

还有另一种方式,虽然这需要启用 extglob 功能:

echo ${string/#+(0)/}
于 2013-11-08T14:57:08.820 回答
7

在 cron 作业生成器脚本中处理分钟和小时,我发现 08 和 09 前面的前导零会导致 bash 认为该值是无效的八进制数。该脚本不能只去除前导零,因为单个零仍然有效。解决方案是通过管道连接到 bc。

HOUR=09
echo $HOUR | bc
9

HOUR=0
echo $HOUR | bc
0

HOUR=14
echo $HOUR | bc
14
于 2018-07-05T16:20:00.627 回答
4

这也是一种在单行中去除前导零的纯 BASH 方式:

string="00123456"
[[ "$string" =~ ^0*(.+)$ ]] && echo "${BASH_REMATCH[1]}"
123456

注意:正则表达式涵盖了将“00000”输入变为“0”的边缘情况。

于 2013-11-08T14:33:03.037 回答
2

从与扩展 glob 模式匹配的字符串的开头删除最长的子字符串+(0),即一个或多个零。

shopt -s extglob
string="0000123456000"
echo ${string##+(0)}

印刷:

123456000

注意:这会将仅包含零的字符串减少为空字符串。

shopt -s extglob
string="0000000000000"
echo ${string##+(0)}

打印一个空字符串。

如果您希望将一串零减少为单个零,您可以使用算术扩展和[base#]n形式来强制算术基数为 10,以防止八进制解释:

string="0000000000000"
echo $((10#$string))

印刷:

0
于 2019-11-18T19:23:19.060 回答