## 11.4 文件的格式化与相关处理
接下来让我们来将文件进行一些简单的编排吧!下面这些动作可以将你的讯息进行排版的动作, 不需要重新以 vim 去编辑,通过数据流重导向配合下面介绍的 printf 功能,以及 awk 指令, 就可以让你的讯息以你想要的模样来输出了!试看看吧!
### 11.4.1 格式化打印: printf
在很多时候,我们可能需要将自己的数据给他格式化输出的! 举例来说,考试卷分数的输出,姓名与科目及分数之间,总是可以稍微作个比较漂亮的版面配置吧? 例如我想要输出下面的样式:
```
Name Chinese English Math Average
DmTsai 80 60 92 77.33
VBird 75 55 80 70.00
Ken 60 90 70 73.33
```
上表的数据主要分成五个字段,各个字段之间可使用 tab 或空白键进行分隔。 请将上表的数据转存成为 printf.txt 文件名,等一下我们会利用这个文件来进行几个小练习的。 因为每个字段的原始数据长度其实并非是如此固定的 (Chinese 长度就是比 Name 要多), 而我就是想要如此表示出这些数据,此时,就得需要打印格式管理员 printf 的帮忙了! printf 可以帮我们将数据输出的结果格式化,而且而支持一些特殊的字符~下面我们就来看看!
```
[dmtsai@study ~]$ printf '打印格式' 实际内容
选项与参数:
关于格式方面的几个特殊样式:
\a 警告声音输出
\b 倒退键(backspace)
\f 清除屏幕 (form feed)
\n 输出新的一行
\r 亦即 Enter 按键
\t 水平的 [tab] 按键
\v 垂直的 [tab] 按键
\xNN NN 为两位数的数字,可以转换数字成为字符。
关于 C 程序语言内,常见的变量格式
%ns 那个 n 是数字, s 代表 string ,亦即多少个字符;
%ni 那个 n 是数字, i 代表 integer ,亦即多少整数码数;
%N.nf 那个 n 与 N 都是数字, f 代表 floating (浮点),如果有小数码数,
假设我共要十个位数,但小数点有两位,即为 %10.2f 啰!
```
接下来我们来进行几个常见的练习。假设所有的数据都是一般文字 (这也是最常见的状态),因此最常用来分隔数据的符号就是 [Tab] 啦!因为 [Tab] 按键可以将数据作个整齐的排列!那么如何利用 printf 呢?参考下面这个范例:
```
范例一:将刚刚上头数据的文件 (printf.txt) 内容仅列出姓名与成绩:(用 [tab] 分隔)
[dmtsai@study ~]$ printf '%s\t %s\t %s\t %s\t %s\t \n' $(cat printf.txt)
Name Chinese English Math Average
DmTsai 80 60 92 77.33
VBird 75 55 80 70.00
Ken 60 90 70 73.33
```
由于 printf 并不是管线命令,因此我们得要通过类似上面的功能,将文件内容先提出来给 printf 作为后续的数据才行。 如上所示,我们将每个数据都以 [tab] 作为分隔,但是由于 Chinese 长度太长,导致 English 中间多了一个 [tab] 来将数据排列整齐!啊~结果就看到数据对齐结果的差异了!
另外,在 printf 后续的那一段格式中,%s 代表一个不固定长度的字串,而字串与字串中间就以 \t 这个 [tab] 分隔符号来处理!你要记得的是,由于 \t 与 %s 中间还有空格,因此每个字串间会有一个 [tab] 与一个空白键的分隔喔!
既然每个字段的长度不固定会造成上述的困扰,那我将每个字段固定就好啦!没错没错!这样想非常好! 所以我们就将数据给他进行固定字段长度的设计吧!
```
范例二:将上述数据关于第二行以后,分别以字串、整数、小数点来显示:
[dmtsai@study ~]$ printf '%10s %5i %5i %5i %8.2f \n' $(cat printf.txt | grep -v Name)
DmTsai 80 60 92 77.33
VBird 75 55 80 70.00
Ken 60 90 70 73.33
```
上面这一串格式想必您看得很辛苦!没关系!一个一个来解释!上面的格式共分为五个字段, %10s 代表的是一个长度为 10 个字符的字串字段,%5i 代表的是长度为 5 个字符的数字字段,至于那个 %8.2f 则代表长度为 8 个字符的具有小数点的字段,其中小数点有两个字符宽度。我们可以使用下面的说明来介绍 %8.2f 的意义:
> 字符宽度: 12345678
> %8.2f意义:00000.00
如上所述,全部的宽度仅有 8 个字符,整数部分占有 5 个字符,小数点本身 (.) 占一位,小数点下的位数则有两位。 这种格式经常使用于数值程序的设计中!这样了解乎?自己试看看如果要将小数点位数变成 1 位又该如何处理?
printf 除了可以格式化处理之外,他还可以依据 ASCII 的数字与图形对应来显示数据喔[[3]](#ps3)! 举例来说 16 进位的 45 可以得到什么 ASCII 的显示图 (其实是字符啦)?
```
范例三:列出 16 进位数值 45 代表的字符为何?
[dmtsai@study ~]$ printf '\x45\n'
E
# 这东西也很好玩~他可以将数值转换成为字符,如果你会写 script 的话,
# 可以自行测试一下,由 20~80 之间的数值代表的字符是啥喔! ^_^
```
printf 的使用相当的广泛喔!包括等一下后面会提到的 awk 以及在 C 程序语言当中使用的屏幕输出, 都是利用 printf 呢!鸟哥这里也只是列出一些可能会用到的格式而已,有兴趣的话,可以自行多作一些测试与练习喔! ^_^
![鸟哥的图示](https://box.kancloud.cn/2016-05-13_5735736501917.gif "鸟哥的图示")
**Tips** 打印格式化这个 printf 指令,乍看之下好像也没有什么很重要的~ 不过,如果你需要自行撰写一些软件,需要将一些数据在屏幕上头漂漂亮亮的输出的话, 那么 printf 可也是一个很棒的工具喔!
### 11.4.2 awk:好用的数据处理工具
awk 也是一个非常棒的数据处理工具!相较于 sed 常常作用于一整个行的处理, awk 则比较倾向于一行当中分成数个“字段”来处理。因此,awk 相当的适合处理小型的数据数据处理呢!awk 通常运行的模式是这样的:
```
[dmtsai@study ~]$ awk '条件类型1{动作1} 条件类型2{动作2} ...' filename
```
awk 后面接两个单引号并加上大括号 {} 来设置想要对数据进行的处理动作。 awk 可以处理后续接的文件,也可以读取来自前个指令的 standard output 。 但如前面说的, awk 主要是处理“每一行的字段内的数据”,而默认的“字段的分隔符号为 "空白键" 或 "[tab]键" ”!举例来说,我们用 last 可以将登陆者的数据取出来,结果如下所示:
```
[dmtsai@study ~]$ last -n 5 <==仅取出前五行
dmtsai pts/0 192.168.1.100 Tue Jul 14 17:32 still logged in
dmtsai pts/0 192.168.1.100 Thu Jul 9 23:36 - 02:58 (03:22)
dmtsai pts/0 192.168.1.100 Thu Jul 9 17:23 - 23:36 (06:12)
dmtsai pts/0 192.168.1.100 Thu Jul 9 08:02 - 08:17 (00:14)
dmtsai tty1 Fri May 29 11:55 - 12:11 (00:15)
```
若我想要取出帐号与登陆者的 IP ,且帐号与 IP 之间以 [tab] 隔开,则会变成这样:
```
[dmtsai@study ~]$ last -n 5 | awk '{print $1 "\t" $3}'
dmtsai 192.168.1.100
dmtsai 192.168.1.100
dmtsai 192.168.1.100
dmtsai 192.168.1.100
dmtsai Fri
```
上表是 awk 最常使用的动作!通过 print 的功能将字段数据列出来!字段的分隔则以空白键或 [tab] 按键来隔开。 因为不论哪一行我都要处理,因此,就不需要有 "条件类型" 的限制!我所想要的是第一栏以及第三栏, 但是,第五行的内容怪怪的~这是因为数据格式的问题啊!所以啰~使用 awk 的时候,请先确认一下你的数据当中,如果是连续性的数据,请不要有空格或 [tab] 在内,否则,就会像这个例子这样,会发生误判喔!
另外,由上面这个例子你也会知道,在 awk 的括号内,每一行的每个字段都是有变量名称的,那就是 $1, $2... 等变量名称。以上面的例子来说, dmtsai 是 $1 ,因为他是第一栏嘛!至于 192.168.1.100 是第三栏, 所以他就是 $3 啦!后面以此类推~呵呵!还有个变量喔!那就是 $0 ,$0 代表“一整列数据”的意思~以上面的例子来说,第一行的 $0 代表的就是“dmtsai .... ”那一行啊! 由此可知,刚刚上面五行当中,整个 awk 的处理流程是:
1. 读入第一行,并将第一行的数据填入 $0, $1, $2.... 等变量当中;
2. 依据 "条件类型" 的限制,判断是否需要进行后面的 "动作";
3. 做完所有的动作与条件类型;
4. 若还有后续的“行”的数据,则重复上面 1~3 的步骤,直到所有的数据都读完为止。
经过这样的步骤,你会晓得, awk 是“以行为一次处理的单位”, 而“以字段为最小的处理单位”。好了,那么 awk 怎么知道我到底这个数据有几行?有几栏呢?这就需要 awk 的内置变量的帮忙啦~
| 变量名称 | 代表意义 |
| --- | --- |
| NF | 每一行 ($0) 拥有的字段总数 |
| NR | 目前 awk 所处理的是“第几行”数据 |
| FS | 目前的分隔字符,默认是空白键 |
我们继续以上面 last -n 5 的例子来做说明,如果我想要:
* 列出每一行的帐号(就是 $1);
* 列出目前处理的行数(就是 awk 内的 NR 变量)
* 并且说明,该行有多少字段(就是 awk 内的 NF 变量)
则可以这样:
![鸟哥的图示](https://box.kancloud.cn/2016-05-13_5735736501917.gif "鸟哥的图示")
**Tips** 要注意喔,awk 后续的所有动作是以单引号“ ' ”括住的,由于单引号与双引号都必须是成对的, 所以, awk 的格式内容如果想要以 print 打印时,记得非变量的文字部分,包含上一小节 [printf](../Text/index.html#printf) 提到的格式中,都需要使用双引号来定义出来喔!因为单引号已经是 awk 的指令固定用法了!
```
[dmtsai@study ~]$ last -n 5| awk '{print $1 "\t lines: " NR "\t columns: " NF}'
dmtsai lines: 1 columns: 10
dmtsai lines: 2 columns: 10
dmtsai lines: 3 columns: 10
dmtsai lines: 4 columns: 10
dmtsai lines: 5 columns: 9
# 注意喔,在 awk 内的 NR, NF 等变量要用大写,且不需要有钱字号 $ 啦!
```
这样可以了解 NR 与 NF 的差别了吧?好了,下面来谈一谈所谓的 "条件类型" 了吧!
* awk 的逻辑运算字符
既然有需要用到 "条件" 的类别,自然就需要一些逻辑运算啰~例如下面这些:
| 运算单元 | 代表意义 |
| --- | --- |
| > | 大于 |
| < | 小于 |
| >= | 大于或等于 |
| <= | 小于或等于 |
| == | 等于 |
| != | 不等于 |
值得注意的是那个“ == ”的符号,因为:
* 逻辑运算上面亦即所谓的大于、小于、等于等判断式上面,习惯上是以“ == ”来表示;
* 如果是直接给予一个值,例如变量设置时,就直接使用 = 而已。
好了,我们实际来运用一下逻辑判断吧!举例来说,在 /etc/passwd 当中是以冒号 ":" 来作为字段的分隔, 该文件中第一字段为帐号,第三字段则是 UID。那假设我要查阅,第三栏小于 10 以下的数据,并且仅列出帐号与第三栏, 那么可以这样做:
```
[dmtsai@study ~]$ cat /etc/passwd | awk '{FS=":"} $3 < 10 {print $1 "\t " $3}'
root:x:0:0:root:/root:/bin/bash
bin 1
daemon 2
....(以下省略)....
```
有趣吧!不过,怎么第一行没有正确的显示出来呢?这是因为我们读入第一行的时候,那些变量 $1, $2... 默认还是以空白键为分隔的,所以虽然我们定义了 FS=":" 了, 但是却仅能在第二行后才开始生效。那么怎么办呢?我们可以预先设置 awk 的变量啊! 利用 BEGIN 这个关键字喔!这样做:
```
[dmtsai@study ~]$ cat /etc/passwd | awk 'BEGIN {FS=":"} $3 < 10 {print $1 "\t " $3}'
root 0
bin 1
daemon 2
......(以下省略)......
```
很有趣吧!而除了 BEGIN 之外,我们还有 END 呢!另外,如果要用 awk 来进行“计算功能”呢?以下面的例子来看, 假设我有一个薪资数据表文件名为 pay.txt ,内容是这样的:
```
Name 1st 2nd 3th
VBird 23000 24000 25000
DMTsai 21000 20000 23000
Bird2 43000 42000 41000
```
如何帮我计算每个人的总额呢?而且我还想要格式化输出喔!我们可以这样考虑:
* 第一行只是说明,所以第一行不要进行加总 (NR==1 时处理);
* 第二行以后就会有加总的情况出现 (NR>=2 以后处理)
```
[dmtsai@study ~]$ cat pay.txt | \
> awk 'NR==1{printf "%10s %10s %10s %10s %10s\n",$1,$2,$3,$4,"Total" }
> NR>=2{total = $2 + $3 + $4
> printf "%10s %10d %10d %10d %10.2f\n", $1, $2, $3, $4, total}'
Name 1st 2nd 3th Total
VBird 23000 24000 25000 72000.00
DMTsai 21000 20000 23000 64000.00
Bird2 43000 42000 41000 126000.00
```
上面的例子有几个重要事项应该要先说明的:
* awk 的指令间隔:所有 awk 的动作,亦即在 {} 内的动作,如果有需要多个指令辅助时,可利用分号“;”间隔, 或者直接以 [Enter] 按键来隔开每个指令,例如上面的范例中,鸟哥共按了三次 [enter] 喔!
* 逻辑运算当中,如果是“等于”的情况,则务必使用两个等号“==”!
* 格式化输出时,在 printf 的格式设置当中,务必加上 \n ,才能进行分行!
* 与 bash shell 的变量不同,在 awk 当中,变量可以直接使用,不需加上 $ 符号。
利用 awk 这个玩意儿,就可以帮我们处理很多日常工作了呢!真是好用的很~ 此外, awk 的输出格式当中,常常会以 [printf](../Text/index.html#printf) 来辅助,所以, 最好你对 printf 也稍微熟悉一下比较好啦!另外, awk 的动作内 {} 也是支持 if (条件) 的喔! 举例来说,上面的指令可以修订成为这样:
```
[dmtsai@study ~]$ cat pay.txt | \
> awk '{if(NR==1) printf "%10s %10s %10s %10s %10s\n",$1,$2,$3,$4,"Total"}
> NR>=2{total = $2 + $3 + $4
> printf "%10s %10d %10d %10d %10.2f\n", $1, $2, $3, $4, total}'
```
你可以仔细的比对一下上面两个输入有啥不同~从中去了解两种语法吧!我个人是比较倾向于使用第一种语法, 因为会比较有统一性啊! ^_^
除此之外, awk 还可以帮我们进行循环计算喔!真是相当的好用!不过,那属于比较进阶的单独课程了, 我们这里就不再多加介绍。如果你有兴趣的话,请务必参考延伸阅读中的相关链接喔 [[4]](#ps4)。
### 11.4.3 文件比对工具
什么时候会用到文件的比对啊?通常是“同一个套装软件的不同版本之间,比较配置文件与原始文件的差异”。 很多时候所谓的文件比对,通常是用在 ASCII 纯文本文件的比对上的!那么比对文件的指令有哪些?最常见的就是 diff 啰! 另外,除了 diff 比对之外,我们还可以借由 cmp 来比对非纯文本文件!同时,也能够借由 diff 创建的分析档, 以处理补丁 (patch) 功能的文件呢!就来玩玩先!
* diff
diff 就是用在比对两个文件之间的差异的,并且是以行为单位来比对的!一般是用在 ASCII 纯文本文件的比对上。 由于是以行为比对的单位,因此 diff 通常是用在同一的文件(或软件)的新旧版本差异上! 举例来说,假如我们要将 /etc/passwd 处理成为一个新的版本,处理方式为: 将第四行删除,第六行则取代成为“no six line”,新的文件放置到 /tmp/test 里面,那么应该怎么做?
```
[dmtsai@study ~]$ mkdir -p /tmp/testpw <==先创建测试用的目录
[dmtsai@study ~]$ cd /tmp/testpw
[dmtsai@study testpw]$ cp /etc/passwd passwd.old
[dmtsai@study testpw]$ cat /etc/passwd | sed -e '4d' -e '6c no six line' > passwd.new
# 注意一下, sed 后面如果要接超过两个以上的动作时,每个动作前面得加 -e 才行!
# 通过这个动作,在 /tmp/testpw 里面便有新旧的 passwd 文件存在了!
```
接下来讨论一下关于 diff 的用法吧!
```
[dmtsai@study ~]$ diff [-bBi] from-file to-file
选项与参数:
from-file :一个文件名,作为原始比对文件的文件名;
to-file :一个文件名,作为目的比对文件的文件名;
注意,from-file 或 to-file 可以 - 取代,那个 - 代表“Standard input”之意。
-b :忽略一行当中,仅有多个空白的差异(例如 "about me" 与 "about me" 视为相同
-B :忽略空白行的差异。
-i :忽略大小写的不同。
范例一:比对 passwd.old 与 passwd.new 的差异:
[dmtsai@study testpw]$ diff passwd.old passwd.new
4d3 <==左边第四行被删除 (d) 掉了,基准是右边的第三行
< adm:x:3:4:adm:/var/adm:/sbin/nologin <==这边列出左边(<)文件被删除的那一行内容
6c5 <==左边文件的第六行被取代 (c) 成右边文件的第五行
< sync:x:5:0:sync:/sbin:/bin/sync <==左边(<)文件第六行内容
---
> no six line <==右边(>)文件第五行内容
# 很聪明吧!用 diff 就把我们刚刚的处理给比对完毕了!
```
用 diff 比对文件真的是很简单喔!不过,你不要用 diff 去比对两个完全不相干的文件,因为比不出个啥咚咚! 另外, diff 也可以比对整个目录下的差异喔!举例来说,我们想要了解一下不同的开机执行等级 (runlevel) 内容有啥不同?假设你已经知道执行等级 0 与 5 的启动脚本分别放置到 /etc/rc0.d 及 /etc/rc5.d , 则我们可以将两个目录比对一下:
```
[dmtsai@study ~]$ diff /etc/rc0.d/ /etc/rc5.d/
Only in /etc/rc0.d/: K90network
Only in /etc/rc5.d/: S10network
```
我们的 diff 很聪明吧!还可以比对不同目录下的相同文件名的内容,这样真的很方便喔~
* cmp
相对于 diff 的广泛用途, cmp 似乎就用的没有这么多了~ cmp 主要也是在比对两个文件,他主要利用“字节”单位去比对, 因此,当然也可以比对 binary file 啰~(还是要再提醒喔, diff 主要是以“行”为单位比对, cmp 则是以“字节”为单位去比对,这并不相同!)
```
[dmtsai@study ~]$ cmp [-l] file1 file2
选项与参数:
-l :将所有的不同点的字节处都列出来。因为 cmp 默认仅会输出第一个发现的不同点。
范例一:用 cmp 比较一下 passwd.old 及 passwd.new
[dmtsai@study testpw]$ cmp passwd.old passwd.new
passwd.old passwd.new differ: char 106, line 4
```
看到了吗?第一个发现的不同点在第四行,而且字节数是在第 106 个字节处!这个 cmp 也可以用来比对 binary 啦! ^_^
* patch
patch 这个指令与 diff 可是有密不可分的关系啊!我们前面提到,diff 可以用来分辨两个版本之间的差异, 举例来说,刚刚我们所创建的 passwd.old 及 passwd.new 之间就是两个不同版本的文件。 那么,如果要“升级”呢?就是“将旧的文件升级成为新的文件”时,应该要怎么做呢? 其实也不难啦!就是“先比较先旧版本的差异,并将差异档制作成为补丁文件,再由补丁文件更新旧文件”即可。 举例来说,我们可以这样做测试:
```
范例一:以 /tmp/testpw 内的 passwd.old 与 passwd.new 制作补丁文件
[dmtsai@study testpw]$ diff -Naur passwd.old passwd.new > passwd.patch
[dmtsai@study testpw]$ cat passwd.patch
--- passwd.old 2015-07-14 22:37:43.322535054 +0800 <==新旧文件的信息
+++ passwd.new 2015-07-14 22:38:03.010535054 +0800
@@ -1,9 +1,8 @@ <==新旧文件要修改数据的界定范围,旧文件在 1-9 行,新文件在 1-8 行
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
-adm:x:3:4:adm:/var/adm:/sbin/nologin <==左侧文件删除
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
-sync:x:5:0:sync:/sbin:/bin/sync <==左侧文件删除
+no six line <==右侧新文件加入
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
```
一般来说,使用 diff 制作出来的比较文件通常使用扩展名为 .patch 啰。至于内容就如同上面介绍的样子。 基本上就是以行为单位,看看哪边有一样与不一样的,找到一样的地方,然后将不一样的地方取代掉! 以上面表格为例,新文件看到 - 会删除,看到 + 会加入!好了,那么如何将旧的文件更新成为新的内容呢? 就是将 passwd.old 改成与 passwd.new 相同!可以这样做:
```
# 因为 CentOS 7 默认没有安装 patch 这个软件,因此得要依据之前介绍的方式来安装一下软件!
# 请记得拿出原本光盘并放入光驱当中,这时才能够使用下面的方式来安装软件!
[dmtsai@study ~]$ su -
[root@study ~]# mount /dev/sr0 /mnt
[root@study ~]# rpm -ivh /mnt/Packages/patch-2.*
[root@study ~]# umount /mnt
[root@study ~]# exit
# 通过上述的方式可以安装好所需要的软件,且无须上网。接下来让我们开始操作 patch 啰!
[dmtsai@study ~]$ patch -pN < patch_file <==更新
[dmtsai@study ~]$ patch -R -pN < patch_file <==还原
选项与参数:
-p :后面可以接“取消几层目录”的意思。
-R :代表还原,将新的文件还原成原来旧的版本。
范例二:将刚刚制作出来的 patch file 用来更新旧版数据
[dmtsai@study testpw]$ patch -p0 < passwd.patch
patching file passwd.old
[dmtsai@study testpw]$ ll passwd*
-rw-rw-r--. 1 dmtsai dmtsai 2035 Jul 14 22:38 passwd.new
-rw-r--r--. 1 dmtsai dmtsai 2035 Jul 14 23:30 passwd.old <==文件一模一样!
范例三:恢复旧文件的内容
[dmtsai@study testpw]$ patch -R -p0 < passwd.patch
[dmtsai@study testpw]$ ll passwd*
-rw-rw-r--. 1 dmtsai dmtsai 2035 Jul 14 22:38 passwd.new
-rw-r--r--. 1 dmtsai dmtsai 2092 Jul 14 23:31 passwd.old
# 文件就这样恢复成为旧版本啰
```
为什么这里会使用 -p0 呢?因为我们在比对新旧版的数据时是在同一个目录下, 因此不需要减去目录啦!如果是使用整体目录比对 (diff 旧目录 新目录) 时, 就得要依据创建 patch 文件所在目录来进行目录的删减啰!
更详细的 patch 用法我们会在后续的第五篇的[源代码编译 (第二十一章)](../Text/index.html#tarball_patch)再跟大家介绍, 这里仅是介绍给你,我们可以利用 diff 来比对两个文件之间的差异, 更可进一步利用这个功能来制作修补文件 (patch file) ,让大家更容易进行比对与升级呢!很不赖吧! ^_^
### 11.4.4 文件打印准备: pr
如果你曾经使用过一些图形接口的文书处理软件的话,那么很容易发现,当我们在打印的时候, 可以同时选择与设置每一页打印时的标头吧!也可以设置页码呢!那么,如果我是在 Linux 下面打印纯文本文件呢 可不可以具有标题啊?可不可以加入页码啊?呵呵!当然可以啊!使用 pr 就能够达到这个功能了。不过, pr 的参数实在太多了,鸟哥也说不完,一般来说,鸟哥都仅使用最简单的方式来处理而已。举例来说,如果想要打印 /etc/man_db.conf 呢?
```
[dmtsai@study ~]$ pr /etc/man_db.conf
2014-06-10 05:35 /etc/man_db.conf Page 1
#
#
# This file is used by the man-db package to configure the man and cat paths.
# It is also used to provide a manpath for those without one by examining
# configure script.
.....(以下省略)......
```
上面特殊字体那一行呢,其实就是使用 pr 处理后所造成的标题啦!标题中会有“文件时间”、“文件文件名”及“页码”三大项目。 更多的 pr 使用,请参考 pr 的说明啊! ^_^
- 鸟哥的Linux私房菜:基础学习篇 第四版
- 目录及概述
- 第零章、计算机概论
- 0.1 电脑:辅助人脑的好工具
- 0.2 个人电脑架构与相关设备元件
- 0.3 数据表示方式
- 0.4 软件程序运行
- 0.5 重点回顾
- 0.6 本章习题
- 0.7 参考资料与延伸阅读
- 第一章、Linux是什么与如何学习
- 1.1 Linux是什么
- 1.2 Torvalds的Linux发展
- 1.3 Linux当前应用的角色
- 1.4 Linux 该如何学习
- 1.5 重点回顾
- 1.6 本章习题
- 1.7 参考资料与延伸阅读
- 第二章、主机规划与磁盘分区
- 2.1 Linux与硬件的搭配
- 2.2 磁盘分区
- 2.3 安装Linux前的规划
- 2.4 重点回顾
- 2.5 本章习题
- 2.6 参考资料与延伸阅读
- 第三章、安装 CentOS7.x
- 3.1 本练习机的规划--尤其是分区参数
- 3.2 开始安装CentOS 7
- 3.3 多重开机安装流程与管理(Option)
- 3.4 重点回顾
- 3.5 本章习题
- 3.6 参考资料与延伸阅读
- 第四章、首次登陆与线上求助
- 4.1 首次登陆系统
- 4.2 文字模式下指令的下达
- 4.3 Linux系统的线上求助man page与info page
- 4.4 超简单文书编辑器: nano
- 4.5 正确的关机方法
- 4.6 重点回顾
- 4.7 本章习题
- 4.8 参考资料与延伸阅读
- 第五章、Linux 的文件权限与目录配置
- 5.1 使用者与群组
- 5.2 Linux 文件权限概念
- 5.3 Linux目录配置
- 5.4 重点回顾
- 5.5 本章练习
- 5.6 参考资料与延伸阅读
- 第六章、Linux 文件与目录管理
- 6.1 目录与路径
- 6.2 文件与目录管理
- 6.3 文件内容查阅
- 6.4 文件与目录的默认权限与隐藏权限
- 6.5 指令与文件的搜寻
- 6.6 极重要的复习!权限与指令间的关系
- 6.7 重点回顾
- 6.8 本章习题:
- 6.9 参考资料与延伸阅读
- 第七章、Linux 磁盘与文件系统管理
- 7.1 认识 Linux 文件系统
- 7.2 文件系统的简单操作
- 7.3 磁盘的分区、格式化、检验与挂载
- 7.4 设置开机挂载
- 7.5 内存交换空间(swap)之创建
- 7.6 文件系统的特殊观察与操作
- 7.7 重点回顾
- 7.8 本章习题 - 第一题一定要做
- 7.9 参考资料与延伸阅读
- 第八章、文件与文件系统的压缩,打包与备份
- 8.1 压缩文件的用途与技术
- 8.2 Linux 系统常见的压缩指令
- 8.3 打包指令: tar
- 8.4 XFS 文件系统的备份与还原
- 8.5 光盘写入工具
- 8.6 其他常见的压缩与备份工具
- 8.7 重点回顾
- 8.8 本章习题
- 8.9 参考资料与延伸阅读
- 第九章、vim 程序编辑器
- 9.1 vi 与 vim
- 9.2 vi 的使用
- 9.3 vim 的额外功能
- 9.4 其他 vim 使用注意事项
- 9.5 重点回顾
- 9.6 本章练习
- 9.7 参考资料与延伸阅读
- 第十章、认识与学习BASH
- 10.1 认识 BASH 这个 Shell
- 10.2 Shell 的变量功能
- 10.3 命令别名与历史命令
- 10.4 Bash Shell 的操作环境:
- 10.5 数据流重导向
- 10.6 管线命令 (pipe)
- 10.7 重点回顾
- 10.8 本章习题
- 10.9 参考资料与延伸阅读
- 第十一章、正则表达式与文件格式化处理
- 11.1 开始之前:什么是正则表达式
- 11.2 基础正则表达式
- 11.3 延伸正则表达式
- 11.4 文件的格式化与相关处理
- 11.5 重点回顾
- 11.6 本章习题
- 11.7 参考资料与延伸阅读
- 第十二章、学习 Shell Scripts
- 12.1 什么是 Shell scripts
- 12.2 简单的 shell script 练习
- 12.3 善用判断式
- 12.4 条件判断式
- 12.5 循环 (loop)
- 12.6 shell script 的追踪与 debug
- 12.7 重点回顾
- 12.8 本章习题
- 第十三章、Linux 帐号管理与 ACL 权限设置
- 13.1 Linux 的帐号与群组
- 13.2 帐号管理
- 13.3 主机的细部权限规划:ACL 的使用
- 13.4 使用者身份切换
- 13.5 使用者的特殊 shell 与 PAM 模块
- 13.6 Linux 主机上的使用者讯息传递
- 13.7 CentOS 7 环境下大量创建帐号的方法
- 13.8 重点回顾
- 13.9 本章习题
- 13.10 参考资料与延伸阅读
- 第十四章、磁盘配额(Quota)与进阶文件系统管理
- 14.1 磁盘配额 (Quota) 的应用与实作
- 14.2 软件磁盘阵列 (Software RAID)
- 14.3 逻辑卷轴管理员 (Logical Volume Manager)
- 14.4 重点回顾
- 14.5 本章习题
- 14.6 参考资料与延伸阅读
- 第十五章、例行性工作调度(crontab)
- 15.1 什么是例行性工作调度
- 15.2 仅执行一次的工作调度
- 15.3 循环执行的例行性工作调度
- 15.4 可唤醒停机期间的工作任务
- 15.5 重点回顾
- 15.6 本章习题
- 第十六章、程序管理与 SELinux 初探
- 16.1 什么是程序 (process)
- 16.2 工作管理 (job control)
- 16.3 程序管理
- 16.4 特殊文件与程序
- 16.5 SELinux 初探
- 16.6 重点回顾
- 16.7 本章习题
- 16.8 参考资料与延伸阅读
- 第十七章、认识系统服务 (daemons)
- 17.1 什么是 daemon 与服务 (service)
- 17.2 通过 systemctl 管理服务
- 17.3 systemctl 针对 service 类型的配置文件
- 17.4 systemctl 针对 timer 的配置文件
- 17.5 CentOS 7.x 默认启动的服务简易说明
- 17.6 重点回顾
- 17.7 本章习题
- 17.8 参考资料与延伸阅读
- 第十八章、认识与分析登录文件
- 18.1 什么是登录文件
- 18.2 rsyslog.service :记录登录文件的服务
- 18.3 登录文件的轮替(logrotate)
- 18.4 systemd-journald.service 简介
- 18.5 分析登录文件
- 18.6 重点回顾
- 18.7 本章习题
- 18.8 参考资料与延伸阅读
- 第十九章、开机流程、模块管理与 Loader
- 19.1 Linux 的开机流程分析
- 19.2 核心与核心模块
- 19.3 Boot Loader: Grub2
- 19.4 开机过程的问题解决
- 19.5 重点回顾
- 19.6 本章习题
- 19.7 参考资料与延伸阅读
- 第二十章、基础系统设置与备份策略
- 20.1 系统基本设置
- 20.2 服务器硬件数据的收集
- 20.3 备份要点
- 20.4 备份的种类、频率与工具的选择
- 20.5 鸟哥的备份策略
- 20.6 灾难复原的考虑
- 20.7 重点回顾
- 20.8 本章习题
- 20.9 参考资料与延伸阅读
- 第二十一章、软件安装:源代码与 Tarball
- 20.1 开放源码的软件安装与升级简介
- 21.2 使用传统程序语言进行编译的简单范例
- 21.3 用 make 进行宏编译
- 21.4 Tarball 的管理与建议
- 21.5 函数库管理
- 21.6 检验软件正确性
- 21.7 重点回顾
- 21.8 本章习题
- 21.9 参考资料与延伸阅读
- 第二十二章、软件安装 RPM, SRPM 与 YUM
- 22.1 软件管理员简介
- 22.2 RPM 软件管理程序: rpm
- 22.3 YUM 线上升级机制
- 22.4 SRPM 的使用 : rpmbuild (Optional)
- 22.5 重点回顾
- 22.6 本章习题
- 22.7 参考资料与延伸阅读
- 第二十三章、X Window 设置介绍
- 23.1 什么是 X Window System
- 23.2 X Server 配置文件解析与设置
- 23.3 显卡驱动程序安装范例
- 23.4 重点回顾
- 23.5 本章习题
- 23.6 参考资料与延伸阅读
- 第二十四章、Linux 核心编译与管理
- 24.1 编译前的任务:认识核心与取得核心源代码
- 24.2 核心编译的前处理与核心功能选择
- 24.3 核心的编译与安装
- 24.4 额外(单一)核心模块编译
- 24.5 以最新核心版本编译 CentOS 7.x 的核心
- 24.6 重点回顾
- 24.7 本章习题
- 24.8 参考资料与延伸阅读