【发布时间】:2021-09-03 21:20:57
【问题描述】:
我正在编写一个 shell 脚本,旨在使用 sox 命令编辑音频文件。我遇到了一个以前在 bash 脚本中从未遇到过的奇怪问题:在 sox 中定义空格分隔效果时,该命令将在直接编写该效果时起作用,但当它存储在变量中时则不起作用。这意味着以下工作正常且没有任何问题:
sox ./test.in.wav ./test.out.wav delay 5
但由于某种原因,以下内容不起作用:
IFS=' ' # set IFS to only have a tab character because file is tab-separated
while read -r file effects text; do
sox $file.in.wav $file.out.wav $effects
done <in.txt
...当它的in.txt 被创建时:
printf '%s\t%s\t%s\n' "test" "delay 5" "other text here" >in.txt
错误表明这导致它将输出文件视为另一个输入。
sox FAIL formats: can't open input file `./output.wav': No such file or directory
我尝试了所有我能想到的方法:使用引号 (sox "$file.in.wav" "$file.out.wav" "$effects"),内联变量 (sox $file.in.wav $file.out.wav $(echo $effects)),甚至转义变量内的空格 (effects="delay\ 5")。似乎没有任何效果,一切都会产生错误。为什么一个命令有效而另一个无效,我缺少什么以及如何解决?
【问题讨论】:
-
我试过这个,这就是为什么它很奇怪。
sox ./input.wav ./output.wav "$effects"和sox ./input.wav ./output.wav '$effects'都会产生同样的问题。 -
对,使用数组
effects=(delay 5)然后使用"${effects[@]}" -
这些字符只是向您展示
delay 5只是一个参数的外壳。不是你不想要的东西被添加了;它是调试输出,可让您区分单参数和多参数。 -
如果您希望您的
IFS更改为仅修改read,然后将其放在您的while read行中,如while IFS=$'\t' read -r file effects text; do ...,不要在其他任何地方更改IFS-- 如果您这样做,则更改的范围为read。 -
(不,
IFS不仅改变了read;它还改变了 all 未加引号的扩展的工作方式,因此修改了$effects的含义;它没有t 更改"$effects",但引号强制执行的行为是您不想要的行为)。