#!/bin/sh
export $REG=0x000000
export $DONE=0x4A9FFF
while $REG -le $DONE
do
(($REG+1))
printf 'wm8280_reg get 0x'$REG'\r\n'
sleep 1
done
这会导致错误:
./wm8280_reg_get1.sh: line 3: export: `=000000': not a valid identifier
./wm8280_reg_get1.sh: line 4: export: `=4A9FFF': not a valid identifier
./wm8280_reg_get1.sh: line 6: -le: command not found
我很确定它dash
用于-le
“小于或等于”,但显然我错了。另外,我不确定为什么我的变量是错误的。我做错了什么?
答案1
sh
应该在任何一致的实现(包括最新版本)中工作的标准(POSIX)语法dash
是:
#!/bin/sh -
reg=0x000000
done=0x4A9FFF
while [ "$((reg))" -le "$((done))" ]; do
reg=$((reg + 1))
printf 'wm8280_reg get 0x%06X\r\n' "$reg"
sleep 1
done
如果您需要移植到dash
0.5.5 (2009) 之前的版本,您将需要:
#!/bin/sh -
reg=0x000000
done=0x4A9FFF
while [ "$(($reg))" -le "$(($done))" ]; do
reg=$(($reg + 1))
printf 'wm8280_reg get 0x%06X\r\n' "$reg"
sleep 1
done
POSIX 规范过去对于如何$((reg))
扩展并不太清楚(在文本中仍然不是很清楚,但至少 Open Group 的立场已经在邮件列表和一致性测试套件上阐明)和dash
使用在其算术表达式中不支持裸变量(没有$
),而 的规范"$(($ver))
始终更加清晰。
请注意,$reg
第一次调用后将是十进制,reg=$(($reg + 1))
因此您也可以在开始时将变量转换为十进制。另请注意,它将打印数字 0x1 到 0x4AA000(56 天后);更传统(并且在我看来更清晰)的书写方式是:
#!/bin/sh -
reg=$((0x000001)) done=$((0x4AA000))
while [ "$reg" -le "$done" ]; do
printf 'wm8280_reg get 0x%06X\r\n' "$reg"
sleep 1
reg=$(($reg + 1))
done
另外,不要期望每秒准确地打印一行。运行这些命令所花费的时间将会产生偏差。
细节:
export
就是将变量导出到要运行的命令的环境中。在这里使用它没有意义。这些变量仅在这里用于传递它们的价值作为命令的参数。$
当您想要扩展值时,可以在变量前面放置一个变量。export $reg=0x000000
会运行一个export value-of-reg=0x000000
.while
后面跟着要执行的命令(或命令列表),其退出状态决定循环条件。在这里,我们需要[
可用于执行各种测试(例如整数比较)的命令(在大多数 shell 中内置)。- 不过,这些算术比较运算符
[
仅支持十进制整数常量,因此我们使用 shell 算术扩展(支持十六进制)将它们转换为十进制。 - 化妆品:按照惯例,我们通常对环境变量或应该具有全局变量的变量使用全大写的变量名称范围例如,在使用函数的复杂脚本中。
答案2
这个例子
#!/bin/sh
export $REG=0x000000
export $DONE=0x4A9FFF
while $REG -le $DONE
do
(($REG+1))
printf 'wm8280_reg get 0x'$REG'\r\n'
sleep 1
done
应改变:
- 这两行
export
不应为$
变量添加前缀 - 在表达式周围使用
[
and (或在 before 之前使用)]
$REG -le $DONE
test
- 引用变量时读,如表达式中所示。
- 用于
printf
格式化,而不是字符串连接
所以你会有类似的东西
#!/bin/sh
export REG=0x000000
export DONE=0x4A9FFF
while [ "$REG" -le "$DONE" ]
do
(($REG+1))
printf 'wm8280_reg get 0x%s\r\n' "$REG"
sleep 1
done
这条线
while [ "$REG" -le "$DONE" ]
也可以写成
while test "$REG" -le "$DONE"
(两者都是合法的)。
快速阅读 dash 的手册页并不表明它支持十六进制常量。您可能必须更改这些导出以使用十进制值,例如,
export REG=0
export DONE=489063
然后 printf 可以使用,%06X
而不是%s
, 以十六进制打印值。
使用 cuonglm 的建议,你可以使用
while [ "$((REG))" -le "$((DONE))" ]
和
REG=$(($((REG))+1))
指的是 POSIX shell2.6.4 算术扩展:
仅十进制常数、八进制常数和十六进制- ISO C 标准第 6.4.4.1 节中规定的常量需要被识别为常量。
然而,测试短跑在 Debian 7 和 8 上,增量表达式可能无法按 OP 的预期工作,因为结果是十进制,而假设printf
它是十六进制。另外,REG=((REG+1))
在该版本的 dash 中不起作用。 (当然,bash 是一个不同的故事)。
答案3
好的,谢谢大家的意见。最终脚本如下所示:
#!/bin/sh
export REG=0
export DONE=4890632
while [ "$((REG))" -le "$((DONE))" ]
do
wm8280_reg get $REG >> "wm_reg_dump.txt"
REG=$(($((REG))+1))
done
它在 DASH 中运行并具有所需的输出。当然,代码需要 8 个小时才能运行,但是嘿,设置好之后就不用管它了:)