非法号码 - Shell 脚本
Illegal Number - Shell Script
我的代码工作正常然后第二天我得到
./Desktop/audiolog.sh: 32: [: /proc/: unexpected operator
./Desktop/audiolog.sh: 13: ./Desktop/audiolog.sh: Illegal number: 08
会不会是秒数08?任何指点都将非常感谢
#!/bin/sh
DAY=$(date +%d)
MO=$(date +%m)
YR=$(date +%y)
SE=$(date +%S)
H=$(date +%H)
M=$(date +%M)
NOW=$(date)
DURATION=$(((60 - M) * 60-SE))
PART=$(find /mnt/hgfs/Audio\ Log/ -type f -name "RBLoggerAudio ${DAY}-${MO}-${YR}\ ${H}*" | wc -l)
reset
echo "Recording for $DAY $MO $YR - $H 00"
echo "Started at $NOW"
echo "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
if [ "$PART" -eq 0 ]
then
arecord -f cd -c 1 -d$DURATION -t raw -v -v | lame -b 64 -q8 -mm -r - /mnt/hgfs/Audio\ Log/"RBLoggerAudio "$DAY-$MO-$YR\ $H"00".mp3
else
arecord -f cd -c 1 -d$DURATION -t raw -v -v | lame -b 64 -q8 -mm -r - /mnt/hgfs/Audio\ Log/"RBLoggerAudio "$DAY-$MO-$YR\ $H"00 - Part - "$PART.mp3
fi
pid=$(ps -opid= -C audiolog.sh)
while [ -d /proc/$pid ] ; do
sleep 1
done && ./Desktop/audiolog.sh
改变这个
while [ -d /proc/$pid ] ; do
和
while [ -d "/proc/$pid" ] ; do
问题:前导零
您使用的 Bourne-style shell 将数字上的前导零解释为算术表达式中的八进制符号。如果带前导零的数字实际上不是八进制数,则 shell 对象(“非法数字”),例如
$ n=077
$ echo $(( n ))
63
$ n=088
$ echo $(( n ))
sh: Illegal number: 088
如果您的 /bin/sh
是 bash
,则错误消息略有不同:
bash: 088: value too great for base (error token is "088")
只要您的日期分钟变量 ($M
) 或秒变量 ($SE
) 恰好以前导零开头,后跟数字 8 或 9,执行此操作时就会出现此错误shell 脚本中的算术行:
DURATION=$(((60 - M) * 60-SE))
解决前导零问题
由于你的数字是时间,因此永远不会是负数并且只有一个前导零,你可以让 shell 在变量被替换时去掉单个前导零:
$ M=08
$ SE=09
$ DURATION=$(((60 - M) * 60-SE))
sh: Illegal number: 08
$ DURATION=$(((60 - ${M#0}) * 60-${SE#0}))
$ echo $DURATION
3111
如果您的 /bin/sh
实际上是 bash
,您可以改用 10#
语法(但请注意,这不适用于其他 /bin/sh
shells,例如 Ubuntu 上使用的 dash
,它也不适用于负数,但它确实适用于多个前导零):
$ DURATION=$(((60 - 10#$M) * 60-10#$SE))
对于适用于所有 Bourne-style shell 的通用解决方案,具有任意数量的前导零,正数或负数,您必须避免 shell 算术和诉诸到外部程序,例如遗产 expr
:
$ DURATION=$( expr \( 60 - $M \) \* 60 - $SE )
我觉得expr
曾经是built-in到shells之前shells有自己的算术处理,但是bash
和dash
今天有 built-in,所以它确实需要调用外部程序 expr(1)
,因此比 shell built-in 算法慢几个数量级。在循环中使用它要小心。
Stack Overflow 上还有其他与此类似的问题,但每个问题的答案都只有一半的真实性,而且答案并不适用于所有 Bourne shell 变体中的所有数字。我认为我上面的回答总结了所有可能的情况。
我的代码工作正常然后第二天我得到
./Desktop/audiolog.sh: 32: [: /proc/: unexpected operator
./Desktop/audiolog.sh: 13: ./Desktop/audiolog.sh: Illegal number: 08
会不会是秒数08?任何指点都将非常感谢
#!/bin/sh
DAY=$(date +%d)
MO=$(date +%m)
YR=$(date +%y)
SE=$(date +%S)
H=$(date +%H)
M=$(date +%M)
NOW=$(date)
DURATION=$(((60 - M) * 60-SE))
PART=$(find /mnt/hgfs/Audio\ Log/ -type f -name "RBLoggerAudio ${DAY}-${MO}-${YR}\ ${H}*" | wc -l)
reset
echo "Recording for $DAY $MO $YR - $H 00"
echo "Started at $NOW"
echo "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
if [ "$PART" -eq 0 ]
then
arecord -f cd -c 1 -d$DURATION -t raw -v -v | lame -b 64 -q8 -mm -r - /mnt/hgfs/Audio\ Log/"RBLoggerAudio "$DAY-$MO-$YR\ $H"00".mp3
else
arecord -f cd -c 1 -d$DURATION -t raw -v -v | lame -b 64 -q8 -mm -r - /mnt/hgfs/Audio\ Log/"RBLoggerAudio "$DAY-$MO-$YR\ $H"00 - Part - "$PART.mp3
fi
pid=$(ps -opid= -C audiolog.sh)
while [ -d /proc/$pid ] ; do
sleep 1
done && ./Desktop/audiolog.sh
改变这个
while [ -d /proc/$pid ] ; do
和
while [ -d "/proc/$pid" ] ; do
问题:前导零
您使用的 Bourne-style shell 将数字上的前导零解释为算术表达式中的八进制符号。如果带前导零的数字实际上不是八进制数,则 shell 对象(“非法数字”),例如
$ n=077
$ echo $(( n ))
63
$ n=088
$ echo $(( n ))
sh: Illegal number: 088
如果您的 /bin/sh
是 bash
,则错误消息略有不同:
bash: 088: value too great for base (error token is "088")
只要您的日期分钟变量 ($M
) 或秒变量 ($SE
) 恰好以前导零开头,后跟数字 8 或 9,执行此操作时就会出现此错误shell 脚本中的算术行:
DURATION=$(((60 - M) * 60-SE))
解决前导零问题
由于你的数字是时间,因此永远不会是负数并且只有一个前导零,你可以让 shell 在变量被替换时去掉单个前导零:
$ M=08
$ SE=09
$ DURATION=$(((60 - M) * 60-SE))
sh: Illegal number: 08
$ DURATION=$(((60 - ${M#0}) * 60-${SE#0}))
$ echo $DURATION
3111
如果您的 /bin/sh
实际上是 bash
,您可以改用 10#
语法(但请注意,这不适用于其他 /bin/sh
shells,例如 Ubuntu 上使用的 dash
,它也不适用于负数,但它确实适用于多个前导零):
$ DURATION=$(((60 - 10#$M) * 60-10#$SE))
对于适用于所有 Bourne-style shell 的通用解决方案,具有任意数量的前导零,正数或负数,您必须避免 shell 算术和诉诸到外部程序,例如遗产 expr
:
$ DURATION=$( expr \( 60 - $M \) \* 60 - $SE )
我觉得expr
曾经是built-in到shells之前shells有自己的算术处理,但是bash
和dash
今天有 built-in,所以它确实需要调用外部程序 expr(1)
,因此比 shell built-in 算法慢几个数量级。在循环中使用它要小心。
Stack Overflow 上还有其他与此类似的问题,但每个问题的答案都只有一半的真实性,而且答案并不适用于所有 Bourne shell 变体中的所有数字。我认为我上面的回答总结了所有可能的情况。