我正在尝试编写一个函数,它应该将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但是,当我运行它时:
./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我试过带和不带单引号、双引号和反引号的expr的变体,但似乎永远不能让它来计算算术。我可以确认这样一个简单的命令有效: expr 2*3,但是当我尝试在我的脚本中使用类似的命令时,它失败了。
怎样才能让它简单地计算我的表达式呢?
发布于 2017-08-19 05:46:51
在算术运算中,*不需要转义。此外,一些括号也遗漏了。因此,请替换:
total=$(($hr \* 3600 + $min \* 60 + $sec) \* 1000 + $ms)通过以下方式:
total=$((($hr * 3600 + $min * 60 + $sec) * 1000 + $ms))替代方案
可以简化代码,避免多次调用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"
}旁白: Bash算术和美元符号
在Bash算术上下文中,变量前的美元符号是可选的。例如:
$ a=1; echo "$((1 + a)) and $((1+ $a))"
2 and 2虽然一些风格指南建议在算术上下文中省略$,但有一个关键的区别。正如评论中的Chepner points out所说,对未定义变量的处理方式非常不同:
$ unset a
$ echo $((1 + $a))
bash: 1 + : syntax error: operand expected (error token is "+ ")
$ echo $((1 + a))
1总而言之:
如果希望未定义的变量缺省为零,则省略$.
如果不希望将未定义的变量替换为任何内容,可能会导致无效的表达式,请包含$.
在外壳函数mili中,未定义的变量hr、min等将指示代码错误,我们可能需要一条错误消息来警告我们,并且我们希望包含$。在其他情况下,默认值为零是合理的,我们不会这样做,并且省略$将是正确的。
发布于 2017-08-19 06:02:37
另外几点:
return "$total":返回值是介于0和255之间的整数。当小时/分钟/秒为08或09时,您需要echo "$total"$ mili 11: 22 : 09 ,456 hr is: 11分is: 22 sec is: 09 ms is: 456 bash:(11 * 3600 +22* 60 + 09:值对于基数来说太大(错误标记为"09")
我会写道:
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 ))"
}其中10#强制使用基数为10的数字
然后
$ ms=$(mili 11:22:09.456)
hr is: 11
min is: 22
sec is: 09
ms is: 456
$ echo $ms
40929456发布于 2017-08-19 06:16:23
这里有一个疯狂的选择:
$ mili () {
IFS=., read -r time ms <<<"$1"
ms3=$(cut -c 1-3 <<<"${ms}000")
echo "$(date -u -d "1970-01-01 $time" +%s)$ms3"
}
$ mili 15:41:47,757
56507757
$ mili 15:41:47,75
56507750
$ mili 15:41:47
56507000https://stackoverflow.com/questions/45765276
复制相似问题