尽管在 Mac OS 终端上工作,但 printf 不会在 Cygwin 中打印变量
printf won't print a variable in Cygwin, though working on Mac OS Terminal
我在脚本中有以下代码片段:
bitrate=$(ffmpeg -i "$vidfile" 2>&1 | grep bitrate | \
perl -pe 's/.*bitrate: (\d{1,} .*)\r?\n\r?$//')
echo "$bitrate = $bitrate" #added for debugging
printf "$bitrate = $bitrate\n" #added for debugging
printf " $bitrate $vidfile\n" #added for debugging
printf " %s %s \n\n" "$bitrate" "$vidfile"
此 BASH shell 脚本(减去为调试添加的行)在 Mac OS X 终端上正常工作。当我在 Cygwin 上尝试 运行 时,最后一个和第二个 printf
不打印 $bitrate
变量的值。
来自 运行 的示例输出:
$ bitrate.sh 20180305-01.mov 20180305-02.mov
$bitrate = 31103 kb/s
$bitrate = 31103 kb/s
20180305-01.mov
20180305-01.mov
$bitrate = 30735 kb/s
$bitrate = 30735 kb/s
20180305-02.mov
20180305-02.mov
问题是由于非打印回车 return 字符(有时表示为 \r
或 ^M
或 <CR>
)。 DOS 和 Windows 使用文本行以回车 return 后跟换行符结束的约定,但 unix 只使用换行符。结果,当您将 DOS/Windows-format 行交给 unix 程序(例如 shell)时,它认为换行符是该行的结尾,并将回车视为 return 作为该行内容的一部分。在 Windows(例如 Cygwin)中使用 unix 工具时,这个问题经常发生 。
在这种情况下,我认为这是因为脚本文件本身是 DOS/Windows 格式,但显然不是;所以我不确定马车 return 到底来自哪里(也许 perl
试图成为 Windows-compatible 并输出 DOS/Windows 格式?无论如何,最终结果是变量 bitrate
最后有一个回车符 return 。单独打印它,这是不可见的,但如果你打印它后跟 space 和文件名,它会向终端发送“31103 kb/s\r 20180305-01.mov
”,终端打印“31103 kb/s ",然后回车 return 让它返回到行首(这实际上是 "carriage return" 的意思"),然后在 " 31103 kb/s”,替换它。
解决方案:通过在计算比特率的管道末尾添加 tr -d '\r'
来删除回车 return。
当您怀疑有这样的问题时,有用的故障排除技巧:使用 printf
的 %q
格式打印变量:
$ printf 'the var is %q\n' "$bitratenormal"
the var is 31103\ kb/s
$ printf 'the var is %q\n' "$bitratewithcr"
the var is $'31103 kb/s\r'
...和 运行 文件通过 LC_ALL=C cat -vet
使各种 normally-invisible 字符可见:
$ cat filewithweirdchars
This line is normal
This line ends with a space
This line ends with a tab
This line ends with a carriage return
This line has nonbreaking spaces and “weird” unicode quotes
$ LC_ALL=C cat -vet filewithweirdchars
This line is normal$
This line ends with a space $
This line ends with a tab^I$
This line ends with a carriage return^M$
ThisM-BM- lineM-BM- hasM-BM- nonbreakingM-BM- spaces and M-bM-^@M-^\weirdM-bM-^@M-^] unicode quotes$
我在脚本中有以下代码片段:
bitrate=$(ffmpeg -i "$vidfile" 2>&1 | grep bitrate | \
perl -pe 's/.*bitrate: (\d{1,} .*)\r?\n\r?$//')
echo "$bitrate = $bitrate" #added for debugging
printf "$bitrate = $bitrate\n" #added for debugging
printf " $bitrate $vidfile\n" #added for debugging
printf " %s %s \n\n" "$bitrate" "$vidfile"
此 BASH shell 脚本(减去为调试添加的行)在 Mac OS X 终端上正常工作。当我在 Cygwin 上尝试 运行 时,最后一个和第二个 printf
不打印 $bitrate
变量的值。
来自 运行 的示例输出:
$ bitrate.sh 20180305-01.mov 20180305-02.mov
$bitrate = 31103 kb/s
$bitrate = 31103 kb/s
20180305-01.mov
20180305-01.mov
$bitrate = 30735 kb/s
$bitrate = 30735 kb/s
20180305-02.mov
20180305-02.mov
问题是由于非打印回车 return 字符(有时表示为 \r
或 ^M
或 <CR>
)。 DOS 和 Windows 使用文本行以回车 return 后跟换行符结束的约定,但 unix 只使用换行符。结果,当您将 DOS/Windows-format 行交给 unix 程序(例如 shell)时,它认为换行符是该行的结尾,并将回车视为 return 作为该行内容的一部分。在 Windows(例如 Cygwin)中使用 unix 工具时,这个问题经常发生 。
在这种情况下,我认为这是因为脚本文件本身是 DOS/Windows 格式,但显然不是;所以我不确定马车 return 到底来自哪里(也许 perl
试图成为 Windows-compatible 并输出 DOS/Windows 格式?无论如何,最终结果是变量 bitrate
最后有一个回车符 return 。单独打印它,这是不可见的,但如果你打印它后跟 space 和文件名,它会向终端发送“31103 kb/s\r 20180305-01.mov
”,终端打印“31103 kb/s ",然后回车 return 让它返回到行首(这实际上是 "carriage return" 的意思"),然后在 " 31103 kb/s”,替换它。
解决方案:通过在计算比特率的管道末尾添加 tr -d '\r'
来删除回车 return。
当您怀疑有这样的问题时,有用的故障排除技巧:使用 printf
的 %q
格式打印变量:
$ printf 'the var is %q\n' "$bitratenormal"
the var is 31103\ kb/s
$ printf 'the var is %q\n' "$bitratewithcr"
the var is $'31103 kb/s\r'
...和 运行 文件通过 LC_ALL=C cat -vet
使各种 normally-invisible 字符可见:
$ cat filewithweirdchars
This line is normal
This line ends with a space
This line ends with a tab
This line ends with a carriage return
This line has nonbreaking spaces and “weird” unicode quotes
$ LC_ALL=C cat -vet filewithweirdchars
This line is normal$
This line ends with a space $
This line ends with a tab^I$
This line ends with a carriage return^M$
ThisM-BM- lineM-BM- hasM-BM- nonbreakingM-BM- spaces and M-bM-^@M-^\weirdM-bM-^@M-^] unicode quotes$