使用带有 bc 的变量:语法错误

使用带有 bc 的变量:语法错误

原始问题

这可能更像是一个问题bc,而bash不是 FFmpeg 问题,尽管我也很感激能够防止ffprobe在输出后打印回车符。

在我编写的脚本中,为了使用 FFmpeg 自动执行一些常见任务,我使用以下命令获取两个文件的长度:

length1="$(ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 \"$1\")"
length2="$(ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 outro.mp4)"
read -p "Enter the desired duration of the fade in seconds: " fadeduration

...成功输出如下:

$ echo $length1; echo $length2
177.800000
10.567000
<USER INPUT; usually a 2 followed by ENTER>

但是,尝试使用 bc 对这些变量执行基本计算:

total=$(echo "$length1 +$length2" - "$fadeduration" | bc)
echo $total 

...导致一个空变量。

故障排除流程

我尝试将命令分解为更简单的部分,但是这仍然失败了:

$ echo "$length1 + $length2" | bc
(standard_in) 1: illegal character: ^M
(standard_in) 1: illegal character: ^M

这是因为,由于某种原因,ffprobe命令(至少在我的 MSYS2 构建的二进制文件中)在输出末尾添加了一个 Windows 行结尾,因此也添加了变量。

我通过将输出中tr的回车符去掉来解决了这个问题:

echo "$length1 + $length2" | tr -d $'\r' | bc

当前的问题

但用我原来的计算做同样的事情仍然不起作用:

$ echo "$length1 + $length2 - $fadeduration" | tr -d $'\r' | bc
(standard_in) 2: syntax error

这次bc返回了一个语法错误,这表明 a) 我取得了一些进展,并且 b) 我的编写方式存在问题。

我该如何进行此计算bc以便它成功填充我的变量?

在线发布输出,如下图所示od -c

$ echo "$length1 + $length2 - $fadeduration" | od -c
0000000   1   7   7   .   8   0   0   0   0   0  \r       +       1   0
0000020   .   5   6   7   0   0   0  \r       -      \n

答案1

ffprobe 是一个 Windows 程序,因此其输出包含 CR(回车符)和 LF(换行符)。

CR LF is the sequence \r  \n

我没有 ffprobe,但任何 Windows 程序都可以显示相同

$ touch prova.txt
$ cmd /c dir prova.txt | od -c
0000000       D   a   t   e   n   t   r 204   g   e   r       i   n
0000020   L   a   u   f   w   e   r   k       D   :       i   s   t
0000040   D   A   T   A  \r  \n       V   o   l   u   m   e   s   e   r
...

bc 要求命令以“\n”终止

$ echo -e  "2+4"  | od -c
0000000   2   +   4  \n
0000004
$ echo -e  "2+4"  | bc
6

缺少它,bc 会报告错误

$ echo -e  -n "2+4"  | od -c
0000000   2   +   4
0000003
$ echo -e  -n "2+4"  | bc
(standard_in) 1: syntax error

核对od -c内容echo "$length1 + $length2 - $fadeduration" 可能是缺少最后一项\n,或者太多了

在第一种情况下,你可以使用类似

total=$(echo "$length1 + $length2 - $fadeduration \n" | bc)

否则尝试使用以下方法清理原点的变量

length1="$(ffprobe -v erro .. | tr -d '\r')

答案2

这是其中之一很稀少不将变量括在双引号中的情况也能实现您的需要。

通常我会说(反复!) 变量在使用时应放在双引号中,以防止 shell 在空格处拆分值。但是,在这种情况下,您可以让 shell 在空格处拆分值,因为这不仅包括换行符,还包括回车符,

total=$(echo $length1 + $length2 - $fadeduration | bc)
echo $total

请注意,要使此功能正常工作,您需要进行修改IFS以将其包含\r在它解析的一组空白字符中。我很久以前就在 Cygwin 上做过这件事,这就是为什么当我第一次发布这个答案时我忘记了它:

export IFS=$' \t\r\n'    # bash or other shells understanding $'...' syntax

查看od -c输出,您可以看到它以减号结尾,即没有数值。这解释了(无效)$fadeduration的语法错误。您读取值的代码是正确的( ),所以也许在测试的第二部分您只是忘记设置值了?bc1 + 2 -read -p 'Prompt... ' fadeduration

相关内容