Linux下命令行(二)之文本处理基础
系统管理员工作过程中,总会遇到小的、琐碎的、各种各样的文本处理问题,如果对文本处理不熟,每一次都要查很多的资料去解决这样的小问题,那么系统管理员的工作效率从何而来。因此如何快速写出简短有效的针对特定问题的文本处理程序,是系统管理员的基本功之一,也是能够大大提高系统管理员的工作效率的技能之一。
说是文本处理,其实是对文本流的处理,与此相对的还有二进制流。文本处理就是对输入文本流进行相应的操作、转换然后写入到输出文本流中。我们知道Linux下默认给每个进程打开三个流,分别是标准输入、标准输出以及标准错误流,更底层一点的,这三个流分别对应于文件描述符0、1和2。对于特定的进程,还可以打开自己的流,进行输入输出。文本处理操作就发生在文本从一个流到另一流之间的过程中。
Linux与文本处理相关的命令主要有:cat、head、tail、wc、column、sort、split、join、uniq、tr、cut、diff、patch等,当然还有很多其它的文本处理相关的指令,但是掌握这几个指令,简单的文本处理就是手到擒来的事。
1、cat - 贴出一个文件的内容,从文件中获取输入,并将该文件内容输出到标准输出
指令格式:
$ cat [OPTION]... [FILE]...
cat指令功能虽然简单,但是配合重定向,它就可以将一个文件内容送给任何可以从标准输入获取数据的工具来进行处理。
cat指令本身有一些选项(不太常用),通过这些选项可以在贴出文本流之前就对文本进行简单的处理。
常用选项:
-b 对非空行编号,并显示其行号
-n 对所有行编号,并显示其行号
-E 在每一行后显示$
-T 将制表符显示为^I
实例:
将一个文件的内容送给column指令:
$ cat /etc/passwd | column -s: -t
这条指令的作用将文件/etc/passwd的内容进行按列对齐进行显示。column指令在后面会有详细说明。对于可以直接从从文件中获取数据的指令,这样做显得多此一举,但是对于一些要求从标准输入获取数据的指令来说,通过cat和管道无疑是非常不错的一种方式。
2、head - 用于显示一个文件的前几行
指令格式:
$ head [OPTION]... [FILE]...
head指令用于从文件头开始显示几行,它比cat多出了可以按行选择文件中需要输出的部分。同cat一样,它默认从文件中获取内容,输出到标准输出。当需要对某个文件的头几行、几十行等内容进行文本处理时,head指令就可以帮上忙。
相比于cat,head指令提供的功能可能显得更有用。
常用选项:
-c m 输出文件内容的前m个字节,这里m是一个数字
-n m 输出文件内容的前m行的文本,这里m是一个数字
-n 输出文件内容的前n行,这里n输一个数字
实例:
若只需要/etc/passwd文件前三行内容,并将它送给column指令处理,可以像向下面这样处理:
$ head -3 /etc/passwd | column -s: -t
3、tail - 用于显示一个文件的后几行
指令格式:
$ tail [OPTION]... [FILE]...
tail指令用于从文件结尾开始显示几行,与head指令的作用刚好相反。同样,tail指令从文件中获取数据,输出到标准输出。
常用选项:
-c m 输出后m字节,同样,这里m是一个数字
-n m 输出后m行的文本,这里m是一个数字
-n 输出后n行,这里n输一个数字
实例:
比如需要/etc/passwd文件的第3到10行,可以像下面这样做:
$ head -10 /etc/passwd | tail -7
4、wc - 用于统计一个文本流有多少的字符、单词或单位行
指令格式:
$ wc [OPTION]... [FILE]...
$ wc [OPTION]... --files0-from=F
根据使用的选项的不同,wc指令可以对文件进行按字符、单词和行进行统计。
常用选项:
-c 打印文件的字节数
-m 打印文件的字符数
-w 打印文件的单词个数
-l 打印文件的行数
-L 打印文件的最长一行的长度
--files0-from=F 从文件F中获取文件名
不带任何选项的wc指令将分别打印文件的行数、单词数、以及行数。
实例:
需要注意的是对于中文文本,需使用选项m来获取文件的中文字符个数。比如获取/etc/passwd文件的行数:
$ wc -l /etc/passwd
5、tr - 用于把一组字符转化为另一组字符,或者删除特定字符
指令格式:
$ tr [OPTION]... SET1 [SET2]
tr指令从标准输入获取文本流数据,因此常备用在管道的后端进行字符过滤处理,用来转换或删除文本流的中的指定的字符(集)。
常用选项:
-c 取后边SET1字符集合的补集
-d 删除出文本中出现的包含在SET1字符集中的字符
-s 压缩字符,若文本流中某个字符出现在SET1中且连续多次,则压缩成一个字符,即把多个重复字符变成一个字符
-t 先将文本中出现的包含在SET1中的字符序列截断到字符集SET2的长度,然后进行一一对应的转换
所谓字符集,就是一组字符的集合,对于tr指令而言,更精确地说字符集就是一个字符串。字符集的表示方式如下:
CHAR1-CHAR2 从字符CHAR1到CHAR2的所有字符
[CHAR*] 出现在SET2中,表示重复CHAR字符,直到SET2字符集的长度与SET1长度相同
[CHAR*REPEAT] 重复CHAR字符REPEAT次,这里REPEAT可以十进制或者八进制(以0开始)数字
[:alnum:] 表示所有的字母和数字组成的字符集
[:alpha:] 表示所有字母组成的字符集
[:lower:] 表示所有小写字母组成的字符集
[:upper:] 表示所有大写字母组成的字符集
[:print:] 表示所有可打印的字符组成的字符集,包括空白字符
[:blank:] 表示所有水平空白字符集合
[:cntrl:] 表示所有的控制字符
[:space:] 表示所有的空白字符(包括水平空白字符和垂直空白字符)
这里CHAR表示一个字符,可以是一般可表示的字符,如大小写字母或者数字,也可以是转义字符。转义字符的定义类似于C语言中的转义字符,常用的几个如下:
\n 换行符
\r 回车符
\t 水平制表符
实例:
将一个文件中所有大写字母装换成小写字母:
$ cat test.txt | tr 'A-Z' 'a-z'
$ tr 'A-Z' 'a-z' < test.txt # 等价于上面的形式
使用tr指令需要注意,它并不能直接从文件获取数据,它从标准输入获取数据,因此放在通常管道右边来过滤字符。
6、sort - 用于对文件进行排序
指令格式:
$ sort [OPTION]... [FILE]...
$ sort [OPTION]... --files0-from=F
sort指令按照行对文件进行排序,默认排序方式是ascii字符集的顺序。
常用选项:
-b 忽略前置的空白字符
-d 只考虑字母、数字字符
-M 按月份英文名(三字母缩写)
-n 用于按数字排序,而非按数字字符的ascii码排序
-r 反向排序
--files0-from=F 从文件F中获取文件名
实例:
使用sort对文件的内容进行排序时一定要注意是以什么标准进行排序的,因此上面提到的选项是非常重要的。如下:
$ sort -r test1.txt test2.txt
这条指令对文件test1.txt和文件test2.txt进行合并,然后反向排序并输出。
7、uniq - 打印重复单词中的一个,加上特定选项可以计算重复单词出现的次数
uniq [-c] file
选项含义如下:
c 计算重复单词出现的次数,输出两列,一列是单词出现次数,一列是单词
需要注意的uniq只能用于已经排序的文本才能起到计算或剔除重复的文本行的效果。
一个组合上面的命令的有用的命令如下:
awk '{print $1}' ~/.bash_history | sort | uniq -c | sort -nr | head -10
这条指令的作用就是打印用户最常用的10条命令。
8、column
9、split
10、join