如何检查 bash for 循环中的不等式?

How to check for inequality in bash for loop?

我在 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 循环,这样我就不会收到关于无效语法的错误?

这种形式的 for 循环 用于算术运算。您需要使用 while 循环来代替:

j=$i
while [[ ${1:j:3} != "   " ]]; do
    sleep 0.1
    j=$((j+1))
done

Basically, what I need is for the loop to run through the characters in a string until it finds three consecutive spaces. The string contains Morse code, and each letter is separated by 3 characters (because in American Morse, letters can contain 0, 1, or 2 spaces, so 3 is the minimum letter delimiter).

好吧,这似乎是一种奇怪的方式。 shell 比通过遍历索引扫描字符串有更好的机制来完成这项任务。例如,

# the value of , with the longest suffix matching glob pattern "   *" removed.
letter=${1%%    *}

我不清楚你的示例代码中 sleep 0.1 的目的,但如果你只是模拟通过摩尔斯电码接收信号的时间(完成不同摩尔斯字母的不同时间length),那么可以单独编址。

Afterward, I convert what I have detected to be a complete Morse letter to English and print it out, and then move on to the next Morse characters.

所以我会更像这样:

morse=

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

这涵盖了 所有 摩尔斯字母的循环,顺便说一下,不只是一个。

在 shell 代码中按索引遍历字符串不一定是错误的,但它有不好的代码味道。