首页 > 解决方案 > Bash 中 echo 和 printf 的区别

问题描述

我正在读取文件的行,将每一行转换为 md5 哈希,然后将其写入第二个文件。printf基于使用和 ,我得到了不同的结果echo

printf $line | md5sum | awk '{print $1}' >> md5File.txt

echo $line | md5sum | awk '{print $1}' >> md5File.txt

对于printf00000 变为dcddb75469b4b4875094e14561e573d8,但对于 echo 00000 变为81b4e43a7bcd862f3ac58b5f8568a668

我验证了 00000 的正确 md5 哈希和是,dcddb75469b4b4875094e14561e573d8但我对为什么感到困惑?

标签: bashprintfechomd5sum

解决方案


自动使用echo $line包含换行符 - 您可以使用-n选项抑制它(有时 - 见下文)。所以这不起作用:

echo $line | md5sum | awk '{print $1}' >> md5File.txt

但是在 bash 上这样做:

echo -n $line | md5sum | awk '{print $1}' >> md5File.txt

但并非所有版本echo都有-n选项。回声文档说:

如果第一个操作数是 -n,或者任何操作数包含反斜杠 ('\') 字符,则结果是实现定义的。...在符合 XSI 的系统上,如果第一个操作数是 -n,则应将其视为字符串,而不是选项。

另一种选择是使用 bash 的printf命令。printf 文档说:

添加了 printf 实用程序以提供过去由 echo 提供的功能。但是,由于各种版本的 echo extant 存在不可调和的差异,...

printf可靠的便携方式也是如此。这是一个包含更多详细信息的相关答案: https ://unix.stackexchange.com/questions/65803/why-is-printf-better-than-echo

但是printf如果你不指定格式字符串,那么使用是危险的,所以即使这似乎有效:

printf $line | md5sum | awk '{print $1}' >> md5File.txt

$line当包含百分号或反斜杠时,它将失败。的第一个参数printf是格式字符串,并被特殊处理。如果格式字符串无效,则printf对 stderr 产生错误,对 stdout 产生空字符串,从而给出错误答案。因此,您需要:

printf "%s" "$line" | md5sum | awk '{print $1}' >> md5File.txt

%s告诉期望再有printf一个字符串参数(恰好是$line)并且您得到正确的输出。

有趣的事实:如果您确实想printf添加尾随换行符(在这种情况下您不需要),那么您会

printf "%s\n" "$line" | md5sum | awk '{print $1}' >> md5File.txt

推荐阅读