S6_文本处理

文本统计:wc

wc 是文本统计的常用工具,它可以输出文本的行数、单词数与字符(字节)数。

$ wc file
     427    2768   20131 file

统计中文文本时的问题

wc 在统计中文文本时,会出现一些问题,比如:

$ echo '中文测试' | wc
1       1      13

这里显示文本只有 1 个单词,但是有 13 个字符,这显然是不对的。

对于字符数统计结果,可以使用 wc -m 命令要求 wc 考虑宽字符:

$ echo '中文测试' | wc -m
5

换行符也是一个符号,所以结果为 5(而非 4)。

由于中文文本的单词统计涉及分词算法问题,wc 无法准确统计。

文本比较:diff

diff 工具用于比较两个文件的不同,并列出差异。

$ echo hello > file1
$ echo hallo > file2
$ diff file1 file1
$ diff file1 file2
1c1
< hello
---
> hallo

小知识

加参数 -w 可忽略所有空白字符, -b 可忽略空白字符的数量变化。

假如比较的是两个文本文件,差异之处会被列出;假如比较的是二进制文件,只会指出是否有差异。

文本开头与结尾:head & tail

顾名思义,head 和 tail 分别用来显示开头和结尾指定数量的文字。

以 head 为例,这里给出共同的用法:

  • 不加参数的时候默认显示前 10 行
  • -n <NUM> 指定行数,可简化为 -<NUM>
  • -c <NUM> 指定字节数
$ head file  # 显示 file 前 10 行
$ head -n 25 file  # 显示 file 前 25 行
$ head -25 file  # 显示 file 前 25 行
$ head -c 20 file  # 显示 file 前 20 个字符
$ tail -10 file  # 显示 file 最后 10 行

除此以外,tail 还有一个非常实用的参数 -f:当文件末尾内容增长时,持续输出末尾增加的内容。这个参数常用于动态显示 log 文件的更新(试一试 tail -f /var/log/syslog)。

文本查找:grep

grep 命令可以查找文本中的字符串:

$ grep 'hello' file  # 查找文件 file 中包含 hello 的行
$ ls | grep 'file'  # 查找当前目录下文件名包含 file 的文件
$ grep -i 'Systemd' file  # 查找文件 file 中包含 Systemd 的行(忽略大小写)
$ grep -R 'hello' .  # 递归查找当前目录下内容包含 hello 的文件

不止如此!

grep 事实上是非常强大的查找工具,第九章将在介绍正则表达式语法之后进一步介绍 grep。

文本替换:sed

sed 命令可以替换文本中的字符串:

$ sed 's/hello/world/g' file  # 将文件 file 中的 hello 全局(global)替换为 world 后输出
$ sed 's/hello/world/' file  # 将文件 file 的每一行第一个出现的 hello 替换为 world 后输出
$ echo 'helloworld' | sed 's/hello/world/g'  # 管道也是可以的
$ sed -i 's/hello/world/g' file  # -i 参数会直接写入文件,操作前记得备份哦!
$ sed -i.bak 's/hello/world/g' file  # 当然,也可以让 sed 帮你备份到 file.bak

对于大多数用户来说,最常用 sed 的场合是替换软件源的时候。在阅读了上面的示例之后,以下例子就很简单了:

$ sudo sed -i 's/cn.archive.ubuntu.com/mirrors.ustc.edu.cn/g' /etc/apt/sources.list
$ sudo sed -i 's/archive.ubuntu.com/mirrors.ustc.edu.cn/g' /etc/apt/sources.list
$ sudo sed -i 's/security.ubuntu.com/mirrors.ustc.edu.cn/g' /etc/apt/sources.list

同样不止如此!

sed 事实上是非常强大的文本操作工具,不仅支持正则表达式,而且能够做的操作也不止是替换。第九章将进一步介绍 sed。