Bash 中 echo 和 printf 的区别

问题描述

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

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

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

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

我验证了 00000 的正确 md5 哈希和是 dcddb75469b4b4875094e14561e573d8 但我不明白为什么?

解决方法

使用 <h1>Naming lines</h1> <div class="container naming-lines"> <div class="box box1">I'm box 1</div> <div class="box box2">I'm box 2</div> <div class="box box3">I'm box 3</div> <div class="box box4">I'm box 4</div> <div class="box box5">I'm box 5.</div> <div class="box box6">I'm box 6.</div> <div class="box box7">I'm box 7.</div> <div class="box box8">I'm box 8.</div> <div class="box box9">I'm box 9.</div> <div class="box box10">I'm box 10.</div> <div class="box box11">I'm box 11.</div> <div class="box box12">I'm box 12</div> </div> </div> 会自动包含一个换行符 - 您可以使用 echo $line 选项取消该换行符(有时 - 见下文)。所以这不起作用:

-n

但是在 bash 上是这样的:

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

但并非所有版本的 echo -n $line | md5sum | awk '{print $1}' >> md5File.txt 都有 echo 选项。 echo documentation 说:

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

另一种选择是使用 bash 的 -n 命令。 printf documentation 说:

添加了 printf 实用程序以提供以往由 echo 提供的功能。然而,由于现存的各种版本的回声存在不可调和的差异,...

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

但是如果您不指定格式字符串,则使用 printf 是危险的,因此即使这似乎有效:

printf

printf $line | md5sum | awk '{print $1}' >> md5File.txt 包含百分号或反斜杠时,它会失败。 $line 的第一个参数是格式字符串并被特殊处理。如果格式字符串无效,那么 printf 会向 stderr 产生一个错误,向 stdout 产生一个空字符串,从而给出错误的答案。所以你需要:

printf

printf "%s" "$line" | md5sum | awk '{print $1}' >> md5File.txt 告诉 %s 期望再有一个字符串参数(恰好是 printf)并且您得到正确的输出。

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

printf