如何在 Linux 上使用 Bash printf 命令

与 echo
命令相比,Bash printf
命令允许您使用更精细的控制和更多格式选项写入 Linux 终端窗口。甚至 printf
的怪癖也很有用。
写入终端
它是与程序交互的最基本部分之一。该程序向屏幕写入一些内容,然后您阅读它。即使考虑到 Unix 派生的和 Linux 坚持的命令行程序约定尽可能简洁——许多只在出现问题时才写入终端。告诉用户正在发生的事情,或者即将发生或刚刚发生是基本的编程原语。
Bash shell 具有可以将文本写入终端窗口的 echo
命令。如果变量包含在字符串中,它可以处理变量并显示它们的值,您可以在脚本或命令行中使用它。那么为什么 printf
甚至存在呢? echo
没有涵盖文本编写的内容吗?好吧,printf
提供的功能超出了将字符串写入终端窗口的普通行为。它允许您非常灵活地格式化输出,并且它还有其他技巧。
Bash printf
命令仿照 C 语言的 printf
函数,但也有区别。如果您了解 C,则需要注意这些差异。
编写基本字符串
让我们看看 echo
和 printf
在向终端写入字符串时有何不同。
echo here are some words
printf here are some words

echo
命令打印所有单词,但 printf
只打印第一个单词。此外,printf
没有打印新行。输出与命令提示符相对应。但是,首先要让 printf
作用于所有单词,它们需要被引用。
echo here are some words
printf "here are some words"

这样更好。我们已经打印了所有的单词,但我们仍然没有换行。那是因为使用 printf
时,如果你要求的话,你只会得到一个新行。这可能看起来很痛苦,但它可以让您决定是否包含一个。要使 printf
换行,您需要在字符串中包含“\n
”。这是“换行符”转义序列。
echo here are some words
printf "here are some words\n"

有时你会使用换行符,有时你不会。这是一个 printf
语句使用新行而另一个不使用的情况。
printf "How-To " && printf "Geek\n"

因为第一个 printf
不打印新行,所以第二个 printf
的输出紧跟在“How-To”之后并在同一行。第二个 printf
确实使用 \n
来打印一个新行。这使得命令提示符出现在打印文本下方的行中。
其他转义字符
这里有一些您可以使用的转义字符。你已经看到了“\n
”的作用。
- \n:下移到新行。
- \r:打印回车。这会将输出光标发送回当前行的开头。
- \t:打印制表符。
- \v:打印垂直制表符空间。
- \\:打印反斜杠字符。
- \”:打印引号。
- \b:打印退格字符。
回车转义字符将光标移回当前行的开头。
printf "Honey is the root of all evil\rMoney\n"

printf
命令从左到右处理它的输入。在 printf
遇到“\r
”转义字符之前,该字符串将作为普通文本打印。输出光标移回当前行的开头。
字符串的处理从紧跟在“\r
”字符后面的字母开始。处理余数会导致 printf
打印“Money”,覆盖单词“Honey”。
引号“\
”用于引用字符串,反斜杠“\
”字符表示转义序列。如果要打印这些字符,则需要对它们进行转义带有反斜杠。这告诉 printf
将它们视为文字字符。
printf "This is a \tTab, this is a quotation mark \", and this \\ is a Backslash\n"

使用变量
在 printf
中使用变量与在 echo
中使用它们非常相似。要包含一个变量,比如这个环境变量,像往常一样在它前面加上美元符号“$
”。
printf "Home directory: $HOME\n"

格式化字符串
格式字符串是定义输出格式的字符串。您提供文本和其他值作为要操作的格式字符串的参数。
格式字符串可以包括文本、转义序列和格式说明符。格式说明符告诉 printf
需要什么类型的参数,例如字符串、整数或字符。
这些是最常见的格式说明符。它们都以百分号“%
”开头。要打印百分号,请同时使用两个百分号“%%
”。
- %s:打印一个字符串。
- %c:打印单个字符。
- %d:打印一个整数。
- %f:打印一个浮点数。
- %u:打印一个无符号整数。
- %o:以八进制打印一个值。
- %x:以小写形式打印十六进制值。
- %X:以大写形式打印十六进制值。
- %e:以小写形式以科学记数法打印浮点数。
- %E:以大写形式以科学记数法打印浮点数。
- %%:打印百分号“%”。
printf "How-To %s\n" "Geek"
printf "%s%s %s\n" "How" "-To" "Geek"

第一个命令中的格式字符串包含它自己的一些文本。我们将字符串“Geek”作为参数传递给 printf
。它与“%s
”格式说明符匹配并由其打印。请注意,格式字符串和参数字符串之间只有一个空格。在 C 中,您需要用逗号分隔它们,但对于 printf
的 Bash 版本,使用空格就足够了。
第二个格式字符串仅包含格式说明符和换行转义序列。这三个字符串参数依次由每个“%s
”格式说明符使用。同样,在 C 中,您需要在每个参数之间放置一个逗号,但 Bash printf
让我们忘记了这一点。
要打印不同类型的参数,您只需使用适当的格式说明符即可。这是一个使用 printf
构建的快速数字转换例程。我们将以十进制、八进制和十六进制表示法打印值 15。
printf "Dec: %d\nOct: %o\nHex: %x\n" 15 15 15

让我们稍微修剪一下,这样示例就不那么混乱了。
printf "Hex: %x\n" 15

我们大多数人习惯于看到大写的十六进制值,并且小于 0x10 的值打印有前导零。我们可以通过使用大写十六进制格式说明符“%X
”并在百分号“%
”和“X
”之间放置一个宽度说明符来实现这一点代码>”字符。
这告诉 printf
应该打印参数的字段的宽度。该字段用空格填充。使用这种格式,两位数的值将在没有任何填充的情况下打印出来。
printf "Hex: %2X\n" 15

我们现在得到一个大写的值,打印有一个前导空格。我们可以让 printf
用零而不是空格填充字段,方法是在两者前面放一个零:
printf "Hex: %02X\n" 15

精度说明符允许您设置要包含在输出中的小数点数。
printf "Floating point: %08.3f\n" 9.243546

这使得生成具有整齐对齐输出的结果表变得容易。下一个命令还演示了 Bash printf
的另一个怪癖。如果参数多于格式说明符,则将参数分批输入格式字符串,直到用完所有参数。一次处理的批处理的大小是格式字符串中格式说明符的数量。在 C 语言中,printf
函数调用中的额外参数将被忽略。
printf "Float: %8.3f\n" 9.243546 23.665 8.0021

您也可以对字符串使用宽度和精度说明符。此命令在 10 个字符宽的字段中打印字符串。
printf "%10s %d\n" "coats" 7 "shoes" 22 "Umbrellas" 3

默认情况下,值在其字段中右对齐。要将它们左对齐,请在紧跟在百分号“%
”之后使用减号“-
”。
printf "%-10s %d" "coats" 7 "shoes" 22 "Umbrellas" 3

精度说明符可用于设置打印的最大字符数。我们使用冒号字符“:
”来显示宽度字段的限制。不是“雨伞”这个词是如何被截断的。
printf ":%10.6s:\n" "coats" "shoes" "Umbrellas"
printf ":%-10.6s:\n" "coats" "shoes" "Umbrellas"

宽度说明符甚至可以作为一个参数 传入。使用星号“*
”代替数字说明符,并将宽度作为整数参数传递。
printf "%*s\n" 20 "Rightmost" 12 "Middle" 5 "leftmost"

其他技巧和怪癖
格式字符串中的格式说明符将使用适当类型的值,无论它们是在命令行上作为常规参数提供还是作为 表达式 的输出生成。
打印两个数字的总和:
printf "23+32=%d\n" $((23+32))

此命令打印当前工作目录中的目录数:
printf "There are %d directories\n" $(ls -d */ | wc -l)

此 printf
命令打印从调用另一个命令返回的字符串。
printf "Current user: %s\n" $(whoami)

如果字符串格式说明符“%s
”未随参数一起提供,则 printf
不打印任何内容。
printf "One: %s two: %s\n" "Alpha"

如果错误地为字符串格式说明符“%s
”提供了数值,它会将其打印为字符串并且不会报错。不要用 C printf
来尝试——会发生非常糟糕的事情。你的程序可能会崩溃。但是 Bash printf
毫无怨言地处理了它。
printf "One: %s two: %s\n" "Alpha" 777

如果整数格式说明符“%d
”没有收到任何参数,它将打印为零。
printf "Integer: %d\n"

如果整数格式说明符“%d
”错误地接收到字符串参数,Bash 将打印一条错误消息,而 printf
将打印零。
printf "Integer: %d\n" "Seven"

笨拙的符号可以通过使用它们的 Unicode 编号或“代码点”来生成。这些使用字母“u”后跟它们的 Unicode 值进行转义。
printf "The Euro symbol: \u20AC\n"

要在参数 字符串中包含转义序列,您必须在格式字符串中使用“%b
”格式说明符,而不是“%s
”字符串格式说明符。
printf "%s" "\u20AC\n"
printf "%b" "\u20AC\n"

第一个 printf
语句不处理 Unicode 值,也不识别换行转义序列。第二个 printf
语句使用“%b
”格式说明符。这会正确处理 Unicode 字符并打印新行。
课程用马
有时您需要做的就是将一些文本echo
到终端窗口。但是,当您需要应用一些定位和格式设置时,printf
是完成这项工作的正确工具。
printf "%b" "Tha-" "tha-" "tha-" "that's all folks.\n"