2.3 文件的格式化与相关处理
2.3.1 格式化打印:printf
在输出方面,除了echo还有printf,可以类比c语言中的printf来理解,但是在用法上有着一定的区别。
[haoqiqi@localhost ~]$ printf '打印格式' 实际内容
# 打印格式
# \a:警告声音
# \b:退格键,bankspace
# \f:清除屏幕(form feed)
# \n:换行
# \r:使用enter键
# \t:水平的tab键
# \v:垂直的tab键
# \xNN:NN为两位数的数字,可以转换数字为字符
# 关于c程序语言内,常见的变数格式
# %ns:n为数字,s表示string,即n个字符串
# %ni:n为数字,i表示integer,即n个整数
# %N.nf:n与N都是数字,f表示floating。假设共要10为有效数字,其中小数点后要两位,即为%10.2f
接下来是练习:
需要在主目录下新建print.txt文件,内容如下:
name chinese english math average
DmTsai 80 60 92 77.33
haoqiqi 75 55 80 70
Ken 60 90 70 73.33
# 使用printf函数,将print.txt输出,并使用tab键进行分隔。%s表示一个不固定长度的字符串,字符串之间以\t处理。
[haoqiqi@localhost ~]$ printf '%s\t %s\t %s\t %s\t %s\t \n' $(cat print.txt)
name chinese english math average
DmTsai 80 60 92 77.33
haoqiqi 75 55 80 70
Ken 60 90 70 73.33
可以看出,上面的输出结果的确将其进行了分隔,但是没有对齐,这是因为首行字符串的长度太长,而数字的长度太短,因此导致了不能对齐。
下面将每个字段进行固定,然后重新输出
[haoqiqi@localhost ~]$ printf '%10s %5i %5i %5i %5.2f \n' $(cat print.txt | grep -v name)
DmTsai 80 60 92 77.33
haoqiqi 75 55 80 70
Ken 60 90 70 73.33
# 字符宽度 :12345
# %5.2 :00.00
# 将数字变为ASCII码
[haoqiqi@localhost ~]$ printf '\x45\n'
E
2.3.2 awk:数据处理工具
-
awk的使用
awk常用来与之前学的sed作比较,sed用作处理一整行的动作,awk用作处理一行当中的字段。
awk还可以用来处理后续文件,也可以读取前一个指令的stdout。
其使用规则如下:[haoqiqi@localhost ~]$ awk '条件类型1{动作1} 条件类型2{动作2} ...' filename
# 使用last将前5条登录信息打印出来 [haoqiqi@localhost ~]$ last -n 5 haoqiqi pts/0 :0 Sat Oct 12 21:08 still logged in haoqiqi pts/0 :0 Sat Oct 12 20:49 - 21:08 (00:18) haoqiqi :0 :0 Sat Oct 12 20:43 still logged in reboot system boot 3.10.0-1062.el7. Sat Oct 12 20:40 - 21:19 (00:38) haoqiqi pts/0 :0 Sat Oct 12 16:49 - 17:59 (01:09) # 取出账号与登陆者IP,用tab分隔开 [haoqiqi@localhost ~]$ last -n 5 | awk '{print $1 "\t" $3}' haoqiqi :0 haoqiqi :0 haoqiqi :0 reboot boot haoqiqi :0
对于awk,其是以行为一次处理的单位,且以字段为最小的处理单位。那么,awk是如何得到行数与栏数的数据呢,这就要awk的内建变量来帮忙了。
变量名称 代表意义 NF 每一行{$0}拥有的字段总数 NR 目前awk所处理的是”第几行“数据 FS 目前的分割字符,默认空格键 # 若我想要 # 1.列出每一行的账号 # 2.列出目前处理的行数(NR) # 3.说明该行有多少字段(NF) [haoqiqi@localhost ~]$ last -n 5 | awk '{print $1 "\t lines:" NR "\t colums: " NF}' haoqiqi lines:1 colums: 10 haoqiqi lines:2 colums: 10 haoqiqi lines:3 colums: 10 reboot lines:4 colums: 11 haoqiqi lines:5 colums: 10
-
awk的逻辑运算符
类比于c语言,”=“用来赋值,”==“用来表示等于。运算单元 代表意义 > 大于 < 小于 >= 大于等于 <= 小于等于 == 等于 != 不等于 # 在/etc/passwd中,以“:”作为字段分隔, # 且/etc/passwd中,第一列字段为账号,第三字段为UID # 现需查阅,第三栏中小于10以下爱的数据,仅列出第一、三栏 [haoqiqi@localhost ~]$ cat /etc/passwd | awk '{FS=":"} $3<10 {print $1 "\t" $3}' root:x:0:0:root:/root:/bin/bash bin 1 daemon 2 adm 3 lp 4 sync 5 shutdown 6 halt 7 mail 8
# 可以发现,除了第一行之外,其他行都正确显示了。 # 第一行的错误在于:$1、$2...默认以空格分隔 # 可以使用BEGIN关键词对第一行进行预设 [haoqiqi@localhost ~]$ cat /etc/passwd | awk 'BEGIN{FS=":"} $3<10 {print $1 "\t" $3}' root 0 bin 1 daemon 2 # 现在,第一行正确了
对awk的几项说明:
- awk的指令间隔:所有的awk动作,如果需要多个指令辅助时,可以使用分号“;”分隔,或者直接用ENTER隔开
- 格式化输出时,在printf的格式设定当中,务必加上\n换行
- 与bash shell的变量不同的是,在awk中,变量可以直接使用,不需要加上$符号
2.3.3 文件对比工具
当同一个软件包存在不同版本时,比较配置文件与原始文档的差异时,就需要用到文件对比工具。在windows系统下,我们经常需要用到软件才能进行对比,而且一般都是收费软件;在linux下,我们只需通过指令就能解决了。
-
diff
diff便是用来对比两个文件之间的差异的,对比单位为行,一般用在ACSII纯文本的对比。[haoqiqi@localhost ~]$ diff [-bBi] from-file to-file # -b:忽略一行当中,仅有多个空白的差异 # -B:忽略空白行的差异 # -i:忽略大小写的不同 # from-file:原始对比文件的档名 # to_file :目标对比文件的档名 # 如果使用diff对比两个毫无关系的文档,结果会比较惨...
# 假设我们已经知道了执行等级0与5的脚本 # 分别放入了/etc/rc0.d及/etc/rc5.d当中, # 则我们可以将其对比一下 [haoqiqi@localhost ~]$ diff /etc/rc0.d/ /etc/rc5.d/ 只在 /etc/rc0.d/ 存在:K90network 只在 /etc/rc5.d/ 存在:S10network
-
cmp
cmp主要是以字节为单位进行对比,注意diff以行为单位进行对比[haoqiqi@localhost ~]$ cmp [-l]file1 file2 # -l:将所有的不同点的字节处都列出来,默认只列第一个 [haoqiqi@localhost ~]$ cmp /etc/rc0.d/ /etc/rc5.d/ cmp: /etc/rc0.d/: 是一个目录
-
patch
patch指令与diff指令有着密不可分的关系。之前说diff可以用来分辨两个版本之间的差异,而patch则是用来升级旧文档的。其用法这里暂不学习啦 -
pr
pr是用来做文件打印准备的,但是pr的参数太多,这里仅仅学习最简单的方式。
[haoqiqi@localhost ~]$ pr /etc/man_db.conf
2018-10-31 04:26 /etc/man_db.conf 第 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
# their PATH environment variable. For details see the manpath(5) man page.
# 以下省略....
最上面的一行,就是pr处理都所造成的标题了,其包含“文件时间”、“文件名”、以及“页码”三项。关于更多的pr的使用方法,等到使用到了再学吧。
本节内容就这些了, 欢迎关注我的微信公众号与我联系。