我正在尝试编写一个函数,该函数应该将形式为hr:min:sec,ms(即15:41:47,757)的时间戳转换为毫秒.功能如下:
#!/bin/sh
mili () {
hr=$(echo "$1" | cut -c1-2)
echo "hr is: " $hr
min=$(echo "$1" | cut -c4-5)
echo "min is: " $min
sec=$(echo "$1" | cut -c7-8)
echo "sec is: " $sec
ms=$(echo "$1" | cut -c10-12)
echo "ms is: " $ms
total=$(($hr \* 3600 + $min \* 60 + $sec) \* 1000 + $ms)
return "$total"
#echo "Result is: "$total" "
}
mili $1
Run Code Online (Sandbox Code Playgroud)
但是,当我运行它时:
./mili.sh"15:41:47,757"
我收到以下输出消息:
./mili.sh: command substitution: line 15: syntax error near unexpected token
`\*'
./mili.sh: command substitution: line 15: `($hr \* 3600 + $min \* 60 + $sec)
\* 1000 + $ms'
./mili.sh: line 17: return: : numeric argument required
Run Code Online (Sandbox Code Playgroud)
我尝试过使用和不使用单引号,双引号和反引号的expr变体,但似乎永远无法计算算术.我可以确认这样一个简单的命令:expr 2*3但是当我尝试在我的脚本中使用类似的东西时它会失败.
我怎样才能简单地计算我的表达式呢?
内部算术,*不需要转义.还有一些括号丢失了.因此,替换:
total=$(($hr \* 3600 + $min \* 60 + $sec) \* 1000 + $ms)
Run Code Online (Sandbox Code Playgroud)
附:
total=$((($hr * 3600 + $min * 60 + $sec) * 1000 + $ms))
Run Code Online (Sandbox Code Playgroud)
代码可以简化,无需多次调用cut:
mili() {
IFS=':,' read hr min sec ms <<<"$1"
echo "hr is: " $hr
echo "min is: " $min
echo "sec is: " $sec
echo "ms is: " $ms
total=$((($hr * 3600 + $min * 60 + $sec) * 1000 + $ms))
echo "Total=$total"
return "$total"
}
Run Code Online (Sandbox Code Playgroud)
在bash算术上下文中,变量前的美元符号是可选的.例如:
$ a=1; echo "$((1 + a)) and $((1+ $a))"
2 and 2
Run Code Online (Sandbox Code Playgroud)
虽然一些样式指南建议省略$算术上下文,但有一个关键的区别.正如Chepner在评论中指出的那样,对未定义变量的处理是非常不同的:
$ unset a
$ echo $((1 + $a))
bash: 1 + : syntax error: operand expected (error token is "+ ")
$ echo $((1 + a))
1
Run Code Online (Sandbox Code Playgroud)
总共:
如果您希望未定义的变量默认为零,则省略$.
如果你想要一个未定义的变量替换为空,可能导致无效的表达式,那么包括$.
在外壳的功能mili,一个未定义的变量hr,min等等,都将意味着代码错误,我们可能需要一个错误信息,提醒我们吧,我们将要包括的$.在默认值为零合理的其他情况下,我们不会并且省略它$是正确的.
还有两点:
不要return "$total":返回值是介于0到255之间的整数。您需要echo "$total"
当小时/分钟/秒为08或09-bash将以零开头的数字视为八进制,而8和9是无效的八进制数字时,您将出错。
$ mili 11:22:09,456
hr is: 11
min is: 22
sec is: 09
ms is: 456
bash: (11 * 3600 + 22 * 60 + 09: value too great for base (error token is "09")
Run Code Online (Sandbox Code Playgroud)我会写:
mili () {
IFS=":,." read -r hr min sec ms <<<"$1"
echo "hr is: $hr" >&2
echo "min is: $min" >&2
echo "sec is: $sec" >&2
echo "ms is: $ms" >&2
echo "$(( ((10#$hr * 60 + 10#$min) * 60 + 10#$sec) * 1000 + 10#$ms ))"
}
Run Code Online (Sandbox Code Playgroud)
其中10#力10为底的数
然后
$ ms=$(mili 11:22:09.456)
hr is: 11
min is: 22
sec is: 09
ms is: 456
$ echo $ms
40929456
Run Code Online (Sandbox Code Playgroud)