首页 > 技术文章 > (023) Linux之格式化输出

jplatformx 2015-03-14 15:32 原文

十年运维系列之基础篇 - Linux

作者:曾林 

联系:1494445739@qq.com

网站:www.jplatformx.com

版权:文章未经同意请勿转载


一、引言

      本章继续讨论与文本相关的工具,重点讲一些用于格式化文本输出而非改变文本自身内容的命令。这些命令通常用于文本的打印。

 

二、简单的格式化工具

      首先让我们来看一些简单的格式化工具,它们多数一般执行一些不复杂的操作,并且用于一些小的任务。

 

  1. fold——将文本中的行长度设定为指定长度

      fold是一个将文本行以指定长度分解的操作。与其他命令类似,fold支持一个或多个文件或是标准输入作为输入参数。向fold输入一个简单的文本流,便可以了解其工作方式。如下图:

      这样,我们便能明白fold到底完成了什么操作。echo命令输出的文本被指定了-w选项的fold分解成了片段。本例中,指定了行的宽度为12个字符。如果没有指定行宽,则默认是80个字符。请注意,fold在断行时并不会考虑单词边界。而增加的-s选项,可使fold在到达width字符数前的最后一个有效空格处将原文本行断开。如下图所示:

 

      2. fmt——简单的文本格式化工具

      fmt命令同样会折叠文本,另外还包括更多的功能。它既可以处理文件也可以处理标准输入,并对文本流进行段落格式化。就其基本功能而言,它可以在保留空白行和缩进的同时对文本行进行填充和连接。

      作为演示内容,不如从fmt的帮助手册中复制一些内容。复制内容如下图:

      将这段文字保存在fmt.info文件中。现在假定我们需要重新格式化该文本,以满足每行50个字符宽的规则。那么我们可以输入fmt结合-w选项来完成这样的格式化,命令结果如下所示:

      这个输出结果还真是奇怪。也许,实际上我们应该认真地阅读一下下面的文字,因为它解释了事情发生的原委。

      默认情况下,空白行、单词之间的空格和缩进都保留在输出结果中;不同缩进量的连续输入行并不进行拼接;制表符会在输入中扩展并直接输出。

      所以,fmt保留了第一行的缩进。幸运地是,fmt提供了参数c选项以修整了这个问题。执行结果如下图:

      这样一来,输出结果看起来顺眼了许多。由此可见,通过增加-c选项,我们便得到了理想输出结果。fmt命令有一些非常有趣的选项如下所示:

选项 功能描述
-c 在“冠边缘”模式下运行。此模式保留段落前两行的缩进,随后的行都与第二行的缩进对齐
-p string 只格式化以前缀字符串string开头的行。格式化后,string的内容仍然会作为每个格式化行的前缀。该选项可以用来格式化内容是源代码的文本,例如,任何以“#”号作为声明开头的编程语言或是配置文件都i可以通过指定-p‘#’选项来进行格式化,指定该选项后可以保证只格式化声明中的内容。
-u 字符间隔统一。采取传统的“打字机风格”模式格式化文本,这意味着字符之间间隔一个空格字符,句子之间间隔两个空格字符。该模式对于删除齐行非常有用,所谓齐行就是指文本行被强迫与左右边缘对齐
-w width 格式化文本使每行文本不超过width个字符,默认值是75。请注意,fmt格式化文本时往往由于要保持行平衡而使得行实际宽度比指定宽度小

 

      3. pr——格式化打印文本

      pr命令用于给文本标页码。打印文本时,通常希望将输出内容分成几页,并且每页的顶部和底部都留出几行空白行,这些空白行可以用于插入页眉和页脚。下图示例了将distros.txt文件格式化为一系列非常短的页。

      上例中,结合了-l选项(页长)以及-w选项(页宽)定义了一“页”内容包含15行,每行包含65个字符。pr对distros.txt文件的内容进行分页,页与页之间则用几行空白行隔开,并且创建了一个包含文件修改时间、文件名和页码的默认页眉。更多的pr选项将在以后再细讲。

 

      4. printf——格式化并打印数据

      与本章中涉及的其他命令不一样,printf命令并不适用于管道传输(也就是说它并不支持标准输入),而且在命令行应用中它也不常见(多应用于脚本文件)。

      printf(短语print formatted的缩写),起初是由c语言开发的,后来许多编程语言也都实现了这一功能,也包括shell环境。事实上,在bash中,printf是内置的。如下图:

      printf的用法如下:

      shell> printf "format" arguments

      该命令行给出了一个包含格式说明的字符串,然后将该格式应用于arguments所代表的输入内容,最后格式化结果送至标准输出。如下就是一个简单例子:

      该格式化字符串可以包含文字文本(如“I formatted the string.”)、转义字符(如\n,即换行符)以及以%开头的表示转换规格的字符串。上例中,转换规格%s用于格式化字符串foo并将其结果输出。下表列出了printf常用的数据类型。

指定符 说明
d 将一个数字格式化为有符号的十进制表示形式
f 格式化数字并以浮点数的格式输出
o 将一个整数格式化为八进制格式的整数
s 格式化字符串
x 将一个整数格式化为16进制的数,并且在使用字母时,用小写字母a~f表示
X 与x类似,只是字母用大写字母表示
% 打印文字符号“%”(例如:指定“%%”)

      下图中,例如字符串“888”演示了每个转换说明符的使用效果:

      转换说明符也可以通过增加一些可选组件以对输出效果进行调整。一个完整的转换规格可能会包含如下的内容:

      %[flags][width][.precision]conversion_specification 

      当使用多个可选组件的时候,这些组件必须按照上面的顺序才能被正确编译。下表给出了每个组件的说明:

组件 功能描述
flags

总共有5个不同的flag

  • # 使用替代格式输出。这取决于数据类型。对于o(八进制数)类转换,输出结果以0开头。对于x和X类转换,输出则分别以0x和0X开头
  • 0(零) 用0填充输出。这代表着字段前会填充0,如000380
  • -(破折号) 输出左对齐。默认情况下,printf命令是右对齐
  •  (空格)为正数产生一个前导空格
  • +(加号)正数符号。默认情况下,printf只会输出负数的符号
width 一个数字,该数字指定了最小字段宽度
.precision 对于浮点数,便是指定小数点后的小数精确数。对于字符串转换,precision则指定了输出字符的个数

      下表列出了一些不同格式化的实例:

参数 格式 转换结果 说明
380 %d 380 对整数进行简单的格式化
380 %#x 0x17c 使用替代格式标记将整数格式格式化为一个十六进制数
380 %05d 00380 将整数格式化为至少5个字符宽度的字段,不足位数可以在前面填充0
380 %05.5f 380.00000 将数字格式化后精确到小数点后5位的浮点数,不足位数用0填充。由于指定的最小字段宽度(5)要比格式化后实际的数值位数小,所以此处并没有进行填充
380 %010.5f 0380.00000 把最小字段宽度增加为10,并且0填充可见
380 %+d +380 +标记符表示此数是正数
380 %-d 380 -标记表示左对齐
abcdefghijk %5s abcdefghijk 用最小的字段宽度来最小化字符串
abcdefghijk %.5s abcde 根据字符串的精确位数截断字符串

     同样,printf通常用于脚本文件的表格数据格式化操作,而并不会直接应用于命令行。不过,我们仍然可以用其来解决各种各样的格式化问题。首先,我们可以利用printf输出一些由制表符隔开的字段。具体如下图:

     

 

 

      

 

推荐阅读