@robsean 这篇不够用心,希望下次翻译后,自己通读几遍,会有改善。
This commit is contained in:
Xingyu Wang 2020-09-02 00:11:43 +08:00
parent d005316db8
commit c87f363e92

View File

@ -1,6 +1,6 @@
[#]: collector: (lujun9972) [#]: collector: (lujun9972)
[#]: translator: (robsean) [#]: translator: (robsean)
[#]: reviewer: ( ) [#]: reviewer: (wxy)
[#]: publisher: ( ) [#]: publisher: ( )
[#]: url: ( ) [#]: url: ( )
[#]: subject: (How to use printf to format output) [#]: subject: (How to use printf to format output)
@ -9,20 +9,20 @@
如何使用 printf 来格式化输出 如何使用 printf 来格式化输出
====== ======
开始了解 printf ,一个神秘的,灵活的,和功能丰满的可替换 echo print和 cout 的函数。
![在计算机前喝热饮料][1] > 来了解一下 printf ,一个神秘的、灵活的和功能丰富的函数,可以替换 echo、print 和 cout。
当我开始学习 Unix 时,在很早的过程中,我就被介绍尝试 `echo` 命令。同样在很早的过程中,我最初的 [Python][2] 课程介绍 `print` 函数。拾起 C++ 和 [Java][2] 介绍给我的 `cout``systemout`。似乎每种语言都很自豪地有一个简单的一行产生输出的方法,并且被宣告这种方法的样式过时了。 ![](https://img.linux.net.cn/data/attachment/album/202009/02/001109wp3xdtr27xop25e7.jpg)
但是在我翻开中级教程的第一页后,我遇到了 `printf`,一个晦涩难懂的,诡秘的,和出奇灵活的函数。违背了向初学者隐藏 `printf` 这个令人迷惑的传统,这篇文章旨在介绍不起眼的 `printf` 函数,并解释如何在近乎任意语言中使用它。 当我开始学习 Unix 时,我很早就接触到了 `echo` 命令。同样,我最初的 [Python][2] 课程也涉及到了 `print` 函数。再想起学习 C++ 和 [Java][2] 时学到 `cout``systemout`。似乎每种语言都骄傲地宣称拥有一种方便的单行输出方法,并生怕这种方式要过时一样宣传它。
但是当我翻开中级教程的第一页后,我遇到了 `printf`,一个晦涩难懂的、神秘莫测的,又出奇灵活的函数。本文一反向初学者隐藏 `printf` 这个令人费解的传统,旨在介绍这个不起眼的 `printf` 函数,并解释如何在几乎所有语言中使用它。
### printf 简史 ### printf 简史
术语 `printf` 代表 "格式化输出",可能在 [Algol 68][3] 编程语言中首次出现。自从它包含在 C 中,`printf` 已经在 C++JavaBashPHP 中被重新实施,并且很可能在发生在你最喜欢的 ( C 衍生) 语言中。 术语 `printf` 代表“<ruby>格式化打印<rt>print formatted</rt></ruby>”,它可能最早出现 [Algol 68][3] 编程语言中。自从它被纳入到 C 语言后,`printf` 已经在 C++、Java、Bash、PHP 中一次次重新实现,并且很可能在你最喜欢的 “后 C” 语言中再次出现。
它显然是很受欢迎,并且还有很多人认为它的语法很复杂,尤其是与 `echo``print``cout` 等可替代函数相比尤为明显。例如,在 Bash 中有一个简单的 echo 语句:
显然,它很受欢迎,但很多人认为它的语法很复杂,尤其是与 `echo``print``cout` 等替代的函数相比尤为明显。例如,这是在 Bash 中的一个简单的 `echo` 语句:
``` ```
$ echo hello $ echo hello
@ -30,8 +30,7 @@ hello
$ $
``` ```
在 Bash 中使用 `printf` 有相同的结果: 这是在 Bash 中使用 `printf` 得到同样结果:
``` ```
$ printf "%s\n" hello $ printf "%s\n" hello
@ -43,28 +42,24 @@ $
### printf 输出 ### printf 输出
`printf` 背后的主要概念是:它能够基于来自内容的 _单独的_ 样式信息来格式化输出。例如,这里是 `printf` 认可的作为特殊字符的排列顺序的收藏品。你最喜欢的语言可能有更多一些或更少一些排列顺序,但是通常包含: `printf` 背后的基本思想是:它能够基于与内容*分离的*样式信息来格式化输出。例如,这里是 `printf` 认可的视作特殊字符的特定序列集合。你喜欢的语言可能会有或多或少的序列,但是通常包含:
* `\n`: 新行 * `\n`: 新行
* `\r`: 换行 * `\r`: 回车换行
* `\t`: 水平制表符 * `\t`: 水平制表符
* `\NNN`: 一个使用八进制值的包含一个到三个数字的特殊字节 * `\NNN`: 一个包含一个到三个数字,使用八进制值表示的特殊字节
例如: 例如:
``` ```
$ printf "\t\123\105\124\110\n" $ printf "\t\123\105\124\110\n"
     SETH      SETH
$ $
``` ```
在这个 Bash 示例中, `printf` 在 ASCII 分配到四个八进制值的字符串的字符后渲染一个制表符。使用控制排列顺序来中止行,并生成一个新行 (`\n`) 。 在这个 Bash 示例中, `printf` 渲染一个制表符后,然后是分配给四个八进制值字符串的 ASCII 字符,并以一个生成一个新行(`\n`)的控制序列结束。
使用 `echo` 来尝试相同的东西来生成一点儿完完全全的东西:
如果同样使用 `echo` 来输出会产生更多的字符:
``` ```
$ printf "\t\123\105\124\110\n" $ printf "\t\123\105\124\110\n"
@ -72,8 +67,7 @@ $ printf "\t\123\105\124\110\n"
$ $
``` ```
对于相同是任务,使用 Python 的 `print` 函数,你会发现 Python 的 `print` 命令有你可以期待的更多的东西: 使用 Python 的 `print` 函数来完成同样的任务,你会发现 Python 的 `print` 命令比你想象的要强大:
``` ```
>>> print("\t\123\n") >>> print("\t\123\n")
@ -82,32 +76,29 @@ $
>>> >>>
``` ```
显然Python 的 `print` 包含传统的 `printf` 功能以及简单的 `echo``cout` 的功能 显然Python 的 `print` 包含传统的 `printf` 特性以及简单的 `echo``cout` 的特性
不过,这些示例只包括字面意义上的字符,虽然在一些情况下它们也很有用,它们可能是 `printf` 最不重要的部分。`printf` 的真正的威力在于格式化规范 不过,这些示例包括的只是文字字符,尽管在某些情况下它们也很有用,但它们可能是 `printf` 最不重要的部分。`printf` 的真正的威力在于格式化说明
### 使用 printf 格式化输出 ### 使用 printf 格式化输出
格式化说明符是以一个百分号(`%`)开头的字符。 格式化说明符是以一个百分号(`%`)开头的字符。
常见的格式化说明符包括:
常见的格式化说明符包括:
* `%s`: 字符串 * `%s`: 字符串
* `%d`: 数字 * `%d`: 数字
* `%f`: 浮点数字 * `%f`: 浮点数字
* `%o`: 一个八进制的数字 * `%o`: 一个八进制的数字
这些格式化说明符是 `printf` 语句的占位符,你可以使用一个在其它地方提供的值来替换你的 `printf` 语句中的占位符。这些值在哪里提供取决于你使用的语言和它的语法,这里有一个简单的 Java 例子:
这些格式化说明符在一个 `printf` 语句中是占位符,在你的`printf`语句中,你可以使用一个你在其它地方中提供的值来替换。但是这些提供的值取决于你正在使用的语言及其语法,这里是一个简单的 Java 示例:
``` ```
string var="hello\n"; string var="hello\n";
system.out.printf("%s", var); system.out.printf("%s", var);
``` ```
这个包裹在适当的样板文件中的代码,在执行后,将呈现: 把这个代码包裹在适当的样板文件中,在执行后,将呈现:
``` ```
$ ./example $ ./example
@ -115,8 +106,7 @@ hello
$ $
``` ```
但是,当一个变量的内容更改时,它将会更加有趣。假设你想更新基于不断增加数字的输出: 但是,当一个变量的内容更改时,有意思的地方就来了。假设你想基于不断增加的数字来更新输出:
``` ```
#include <stdio.h> #include <stdio.h>
@ -131,8 +121,7 @@ int main() {
} }
``` ```
编译和运行: 编译并运行:
``` ```
Processing is 1% finished. Processing is 1% finished.
@ -140,12 +129,11 @@ Processing is 1% finished.
Processing is 100% finished. Processing is 100% finished.
``` ```
注意,在代码中的两个 `%` 分解为一个打印`%` 符号。 注意,在代码中的两个 `%` 将被解析为一个打印出来`%` 符号。
### 使用 printf 限制小数位数 ### 使用 printf 限制小数位数
数字可能会变得复杂,`printf` 提供很多格式化选项。你可以对浮点数使用 `%f` 限制打印出多少个小数位。通过把一个点 (`.`)和一个限制的数放置在百分符号和 `f` 之间, 你将告诉 `printf` 渲染多少位小数。这是一个简单的用 Bash 写的简练示例 : 数字也可以是很复杂,`printf` 提供很多格式化选项。你可以对浮点数使用 `%f` 限制打印出多少个小数位。通过把一个点(`.`)和一个限制的数放置在百分符号和 `f` 之间, 你可以告诉 `printf` 打印多少位小数。这是一个简单的用 Bash 写的简练示例:
``` ```
$ printf "%.2f\n" 3.141519 $ printf "%.2f\n" 3.141519
@ -153,8 +141,7 @@ $ printf "%.2f\n" 3.141519
$ $
``` ```
类似的语法也适用于其它的语言。这里是一个 C 语言的示例: 类似的语法也适用于其它的语言。这里是一个 C 语言的示例:
``` ```
#include <math.h> #include <math.h>
@ -170,8 +157,7 @@ int main() {
### 使用 printf 来在数字上添加逗号 ### 使用 printf 来在数字上添加逗号
因为位数大的数字很难分解,所以通常使用一个逗号来断开大的数字。你可以根据需要在由 `printf` 组成的百分号和`d` 之间放置一个撇号(`'`) : 因为位数大的数字很难解读,所以通常使用一个逗号来断开大的数字。你可以在百分号和 `d` 之间放置一个撇号(`'`),让 `printf` 根据需要添加逗号:
``` ```
$ printf "%'d\n" 1024 $ printf "%'d\n" 1024
@ -183,8 +169,7 @@ $
### 使用 printf 来添加前缀零 ### 使用 printf 来添加前缀零
Another common use for `printf` 的另一个常用的用法是对文件名称中的数字强制实行一种特定的格式。例如,如果你在一台计算机上有 10 个按顺序排列的文件,该计算机可能会把 `10.jpg` 排在before `1.jpg` 之前,这可能不是你的本意。当你以编程的方式写一个到文件时,你可以使用 `printf` 来用前缀为0的字符来构成文件名称。这是一个简单的用 Bash 写的简练示例: `printf` 的另一个常用的用法是对文件名称中的数字强制实行一种特定的格式。例如,如果你在一台计算机上有 10 个按顺序排列的文件,计算机可能会把 `10.jpg` 排在 `1.jpg` 之前,这可能不是你的本意。当你以编程的方式写一个到文件时,你可以使用 `printf` 来用前缀为 0 的字符形成文件名称。这是一个简单的用 Bash 写的简练示例:
``` ```
$ printf "%03d.jpg\n" {1..10} $ printf "%03d.jpg\n" {1..10}
@ -198,9 +183,9 @@ $ printf "%03d.jpg\n" {1..10}
### 使用 printf ### 使用 printf
正如这些 `printf` 示例所显示,包括控制字符,尤其是 `\n` ,可能会冗长,并且语法是相当地复杂。这就是为什么开发像 `echo``cout` 之类的快捷方式的原因。不过,如果你是不是地使用 `printf` ,你将会习惯于语法,并且它也将变成你的后天本性。,我看不出任何理由让 `printf` 成为你在日常活动中打印时的 _第一_ 选择,但是它是一个极好的工具来让你足够舒适,当你需要它时,将不会让你降低速度 正如这些 `printf` 示例所显示,包括控制字符,尤其是 `\n` ,可能会冗长,并且语法相对复杂。这就是为什么开发像 `echo``cout` 之类的快捷方式的原因。不过,如果你时不时地使用 `printf` ,你就会习惯于这种语法,并且它也会变成你的习惯。我不认为 `printf` 有任何理由成为你在日常活动中打印时的*首选*,但是它是一个很好的工具,当你需要它时,它不会拖累你
花一些时间学习你所选择语言中的 `printf` ,并且当你需要它时就使用它。它是一个强有力的你不会忘记的随时可用的工具。 花一些时间学习你所选择语言中的 `printf`,并且当你需要时就使用它。它是一个强有力的工具,你不会后悔随时可用的工具。
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
@ -209,7 +194,7 @@ via: https://opensource.com/article/20/8/printf
作者:[Seth Kenlon][a] 作者:[Seth Kenlon][a]
选题:[lujun9972][b] 选题:[lujun9972][b]
译者:[robsean](https://github.com/robsean) 译者:[robsean](https://github.com/robsean)
校对:[校对者ID](https://github.com/校对者ID) 校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出 本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出