Bash bc returns (standard_in) 1: parse error only when part of for loop
Bash bc returns (standard_in) 1: parse error only when part of for loop
我正在遍历整数数组 ${startTimes}
(音频文件中的标记位置,样本)并使用 bc
将这些整数转换为毫秒。我将结果传递到一个新数组 ${msValuesArray}
。如果我一次 运行 每个数组元素一个,它就可以正常工作。如果我 运行 它在 for
循环中:
for i in $(seq 0 ${#startTimes[@]}); do
msValuesArray+=($(bc <<< ${startTimes[i]}/44.1))
done
结果${msValuesArray}
包含预期结果,但终端输出(standard_in) 1: parse error
。
虽然我打算在 shell 脚本中使用它,并且在阅读了此处的其他问题后我了解到将 #!/bin/bash
添加到命令的开头可以避免解析错误,但我仍然不这样做不理解以下内容:
a) 为什么手动将 ${startTimes}
元素传递到 bc
时没有解析错误,而 for
循环也可以,但输出解析错误(在shell 脚本)?
b) 尽管存在解析错误,但我得到了我想要的结果数组。我应该忽略错误吗?
c) 在命令开头添加 #!/bin/bash
时(仍在 shell 脚本之外,仅在命令行中)为什么无法访问结果? (输入 echo ${msValuesArray[@]}
returns 一个空数组。)
d) 当 运行ning 在 shell 脚本中时,是否发生了同样的错误但只是没有打印到终端?
感谢任何帮助。谢谢。
您可以直接遍历数组而不是通过索引:
for t in "${startTimes[@]}"; do
msValuesArray+=($(bc <<< "$t / 44.1"))
done
这使循环更易于阅读。
你得到一个解析错误,因为你试图访问一个不存在的元素(参见 John1024 的回答),所以 bc
只看到 / 44.1
。您不应该忽略该错误。
你应该在此处引用你的字符串,即使在这个例子中它似乎不会引起问题1.
如果你只是在命令行输入#!/bin/bash
,它根本没有任何作用,它只是一个注释。它只在脚本的第一行做一些事情,即指示应该使用什么解释器。如果如您的评论所示,您在一行中输入整个内容
#!/bin/bash; for ... (etc) ...
什么都没有发生。这只是评论。
最后,您截断了结果。如果你想让它们更精确,你可以将 scale
设置为一个合理的值,如
bc <<< "scale = 3; $t / 44.1"
1 诸如(不需要的)分词和通配等问题。 This article 很好地概述了引用的方式和原因。
你有一个 off-by-1 的问题。观察到,对于您的示例 startTimes,seq
生成 10 个数字:
$ startTimes=(0 87053 91463 190062 194472 290520 294930 387582 391992)
$ seq 0 ${#startTimes[@]}
0
1
2
3
4
5
6
7
8
9
问题是 startTimes 只有 9 个条目:
$ declare -p startTimes
declare -a startTimes=([0]="0" [1]="87053" [2]="91463" [3]="190062" [4]="194472" [5]="290520" [6]="294930" [7]="387582" [8]="391992")
当 i=9
时,startTimes[9] 的计算结果为空字符串,这会导致您看到的 bc
错误:
$ i=9; msValuesArray+=($(bc <<< ${startTimes[i]}/44.1))
(standard_in) 1: syntax error
或者,更直接地说:
$ bc <<<"/44.1"
(standard_in) 1: syntax error
我正在遍历整数数组 ${startTimes}
(音频文件中的标记位置,样本)并使用 bc
将这些整数转换为毫秒。我将结果传递到一个新数组 ${msValuesArray}
。如果我一次 运行 每个数组元素一个,它就可以正常工作。如果我 运行 它在 for
循环中:
for i in $(seq 0 ${#startTimes[@]}); do
msValuesArray+=($(bc <<< ${startTimes[i]}/44.1))
done
结果${msValuesArray}
包含预期结果,但终端输出(standard_in) 1: parse error
。
虽然我打算在 shell 脚本中使用它,并且在阅读了此处的其他问题后我了解到将 #!/bin/bash
添加到命令的开头可以避免解析错误,但我仍然不这样做不理解以下内容:
a) 为什么手动将 ${startTimes}
元素传递到 bc
时没有解析错误,而 for
循环也可以,但输出解析错误(在shell 脚本)?
b) 尽管存在解析错误,但我得到了我想要的结果数组。我应该忽略错误吗?
c) 在命令开头添加 #!/bin/bash
时(仍在 shell 脚本之外,仅在命令行中)为什么无法访问结果? (输入 echo ${msValuesArray[@]}
returns 一个空数组。)
d) 当 运行ning 在 shell 脚本中时,是否发生了同样的错误但只是没有打印到终端?
感谢任何帮助。谢谢。
您可以直接遍历数组而不是通过索引:
for t in "${startTimes[@]}"; do
msValuesArray+=($(bc <<< "$t / 44.1"))
done
这使循环更易于阅读。
你得到一个解析错误,因为你试图访问一个不存在的元素(参见 John1024 的回答),所以 bc
只看到 / 44.1
。您不应该忽略该错误。
你应该在此处引用你的字符串,即使在这个例子中它似乎不会引起问题1.
如果你只是在命令行输入#!/bin/bash
,它根本没有任何作用,它只是一个注释。它只在脚本的第一行做一些事情,即指示应该使用什么解释器。如果如您的评论所示,您在一行中输入整个内容
#!/bin/bash; for ... (etc) ...
什么都没有发生。这只是评论。
最后,您截断了结果。如果你想让它们更精确,你可以将 scale
设置为一个合理的值,如
bc <<< "scale = 3; $t / 44.1"
1 诸如(不需要的)分词和通配等问题。 This article 很好地概述了引用的方式和原因。
你有一个 off-by-1 的问题。观察到,对于您的示例 startTimes,seq
生成 10 个数字:
$ startTimes=(0 87053 91463 190062 194472 290520 294930 387582 391992)
$ seq 0 ${#startTimes[@]}
0
1
2
3
4
5
6
7
8
9
问题是 startTimes 只有 9 个条目:
$ declare -p startTimes
declare -a startTimes=([0]="0" [1]="87053" [2]="91463" [3]="190062" [4]="194472" [5]="290520" [6]="294930" [7]="387582" [8]="391992")
当 i=9
时,startTimes[9] 的计算结果为空字符串,这会导致您看到的 bc
错误:
$ i=9; msValuesArray+=($(bc <<< ${startTimes[i]}/44.1))
(standard_in) 1: syntax error
或者,更直接地说:
$ bc <<<"/44.1"
(standard_in) 1: syntax error