我在bash脚本中有以下for循环:
for (( j = i; ${1:j:3} != " "; j=j + 1 ))
do
sleep 0.1
done
printf '%s' "${letter[${1:i:j}]}"
i=$j
运行时,它将导致以下错误的无限循环:
/home/com/morsecoder.sh: line 188: letter: bad array subscript
/home/com/morsecoder.sh: line 184: ((: ... != : syntax error: operand expected (error token is "... != ")
问题在第一行;错误的数组下标错误几乎可以肯定是它的副产品。
我可以看到该错误是由我的${1:j:3} != " "
引起的。基本上,我需要循环运行字符串中的字符,直到找到三个连续的空格为止。该字符串包含莫尔斯电码,每个字母由3个字符分隔(因为在美国莫尔斯电码中,字母可以包含0、1或2个空格,因此3是最小字母分隔符)。
然后,我将检测到的完整的摩尔斯字母转换为英文,然后打印出来,然后移至下一个摩尔斯字符。
printf部分似乎工作正常,但是这里的错误让我感到困惑。我检查了一下,是否正确使用了((
和))
以及!=
来检查不平等。我还尝试将${1:j:3}
括在引号中,但这没有任何作用。我该如何改写for循环,以免收到无效语法的错误?
答案 0 :(得分:4)
for
循环的这种形式仅 用于算术运算。您需要改用while
循环:
j=$i
while [[ ${1:j:3} != " " ]]; do
sleep 0.1
j=$((j+1))
done
答案 1 :(得分:2)
基本上,我需要的是循环运行字符 直到找到三个连续的空格为止。字符串 包含摩尔斯电码,每个字母由3个字符分隔 (因为在美国摩尔斯语中,字母可以包含0、1或2个空格,所以 3是最小字母分隔符。
这似乎是一个奇怪的方法。与通过遍历索引扫描字符串相比,shell具有更好的机制来完成此任务。例如,
# the value of $1, with the longest suffix matching glob pattern " *" removed.
letter=${1%% *}
您对示例代码中的sleep 0.1
的用途尚不清楚,但是如果您只是简单地模拟通过摩尔斯电码接收信号的时间(对于摩尔斯长度不同的字母,请使用不同的时间完成)然后可以单独解决。
然后,我将检测到的信息转换为完整的莫尔斯电码 英文字母并打印出来,然后移至下一个摩尔斯 字符。
所以我会更像这样:
morse=$1
while [[ -n "$morse" ]]; do
# extract the next letter
next_let=${morse%% *}
# sleep for a duration based on the (Morse) length of the letter
sleep "0.${#next_let}"
# print the corresponding decoded Latin letter
printf '%s' "${letter[${next_let}]}"
# remove the Morse letter and its delimiter, if any
morse=${morse:$((${#next_let}+3))}
done
顺便说一句,这涵盖了您遍历所有所有摩尔斯字母的过程。
在外壳代码中按索引遍历字符串不一定是错误的,但是有不好的代码味道。