本文摘录自 Linux 命令行
所有类 Unix 操作系统都严重依赖于几种数据存储的文本文件。所以,有许多用于文本处理的工具。
目前为止,我们已经知道了 nano 和 vim,看过一堆配置文件。文本功能很强大,我们写作用的文档、网页、email、程序源码等都是文本的格式。
cat -A foo.txt会显示文本和非打印字符,如 tab 和空格。cat 也有用来矫正文本的选项,最常用的是 -n(给文本行添加行号)和 -s(禁止输出多个空白行):cat -ns foo.txt# 输入命令后,我们输入 'c','b','a',然后 Ctrl+d 结束输入
chappyzhao@localhost Pics % sort > foo.txt
c
b
a
# 查看文件
chappyzhao@localhost Pics % cat foo.txt
a
b
c
# du 可以确定最大的磁盘空间用户,通常它的输出按照路径名排序。我们把结果管道到 head 命令中,它只会显示前十条,
chappyzhao@localhost Pics % du -s /usr/share/* | head
8 /usr/share/CSI
40 /usr/share/CoreDuetDaemonConfig.bundle
0 /usr/share/ans2_dummy_dir
512 /usr/share/calendar
32 /usr/share/com.apple.languageassetd
1552 /usr/share/cracklib
8904 /usr/share/cups
2928 /usr/share/dict
9840 /usr/share/doc
320 /usr/share/examples
# 在这里我们将产生一个按数值排序的列表,-n(基于字符串的数值来排序)-r(按相反顺序排序,逆序)
chappyzhao@localhost Pics % du -s /usr/share/* | sort -nr | head
130840 /usr/share/tokenizer
49320 /usr/share/man
47992 /usr/share/firmware
...
Sort 程序常见选项
| 选项 | 描述 |
|---|---|
| -b | 默认情况下,对整行进行排序,对每行的第一个字母开始,会忽略每行开头的空格。–ignore-leading-blanks |
| -f | 排序不区分大小写。–ignore-case |
| -n | 基于字符串的数值来排序。–numeric-sort |
| -r | 按相反顺序排序。结果按降序排序。–reverse |
| -k | 对从文本行中的 field1 到 field2 排序,而不是整行。–key=field1[,field2] |
| -m | 把每个参数看成是预先排好序的文件,然后整合成一个文件,不执行额外的排序。–merge |
| -o | 把排好序的结果输出到文件而不是标准输出。–output=file |
| -t | 定义域分隔字符。默认情况下,由空格或制表符分隔。–field-saparator=char |
如果我们想基于文件中的某个字段排序,该怎么做呢?我们这里使用 ls 命令但是不使用 ls 的排序命令:
# k 指定按照第五个字段排序
chappyzhao@localhost Pics % ls -l /usr/bin | sort -nr -k 5 | head
-rwxr-xr-x 1 root wheel 15729904 5 10 05:30 fileproviderctl
-r-xr-xr-x 1 root wheel 12455552 5 10 05:30 parl5.30
-rwxr-xr-x 1 root wheel 6095792 5 10 05:30 kmutil
-rwxr-xr-x 1 root wheel 5056496 5 10 05:30 vim
...
# -t 指定分隔符
chappyzhao@localhost Pics % sort -t ':' -k 7 /etc/passwd | tail
_usbmuxd:*:213:213:iPhone OS Device Helper:/var/db/lockdown:/usr/bin/false
_warmd:*:224:224:Warm Daemon:/var/empty:/usr/bin/false
_webauthserver:*:221:221:Web Auth Server:/var/empty:/usr/bin/false
_windowserver:*:88:88:WindowServer:/var/empty:/usr/bin/false
...
# 创建文件
chappyzhao@localhost Pics % cat > foo.txt
a
b
c
a
b
c
chappyzhao@localhost Pics % sort foo.txt
a
a
b
b
c
c
# 这里使用 sort 的 -u 命令也可以排序,但是更多的选项不如 uniq 多
chappyzhao@localhost Pics % sort -u foo.txt
a
b
c
# 单独使用 uniq 并不能实现排序,uniq **必须接受排好序的数据**
chappyzhao@localhost Pics % uniq foo.txt
a
b
c
a
b
c
chappyzhao@localhost Pics % sort foo.txt | uniq
a
b
c
# 显示重复的数据重复的次数
chappyzhao@localhost Pics % sort foo.txt | uniq -c
2 a
2 b
2 c
通常文本的不同版本比较是很有用的,尤其是对于系统管理员和软件开发人员,如管理员可能会拿现有的配置文件与之前的版本做比较来查找一个错误,而程序员需要经常查看程序的修改。
# 创建两个准备文件
chappyzhao@ChappydeMacBook-Pro Pics % cat > file.txt
a
b
c
f
g
h
chappyzhao@ChappydeMacBook-Pro Pics % cat > file2.txt
b
c
d
e
# comm 产生了三列输出,第一列是第一个文件特有的文本行,第二列是第二个文件特有的,第三个是它们共有的文本行。
chappyzhao@ChappydeMacBook-Pro Pics % comm file.txt file2.txt
a
b
c
d
e
f
g
h
# 可以看到 diff 程序默认的输出格式:< 后对应的是不同文件特有的文本行,以 --- 分割不同文件
chappyzhao@ChappydeMacBook-Pro Pics % diff file.txt file2.txt
1d0
< a
4,6c3,4
< f
< g
< h
---
> d
> e
# 使用 -c 启用了上下文模式,输出结果以两个文件名和它们的时间戳开头,第一个文件用 *** 做标记,第二个文件用 ---做标记,通过这两个标志很容易将它们区分出来,1,6 代表第一个文件从 1 到 6 行,其他符号见下方表格
chappyzhao@ChappydeMacBook-Pro Pics % diff -c file.txt file2.txt
*** file.txt 2022-06-15 10:32:07.000000000 +0800
--- file2.txt 2022-06-15 09:28:38.000000000 +0800
***************
*** 1,6 ****
- a
b
c
! f
! g
! h
--- 1,4 ----
b
c
! d
! e
# 使用 -u 启用了统一模式,可以更加简洁的显示不同 - 代表第一个文件,+ 代表第二个文件
chappyzhao@ChappydeMacBook-Pro Pics % diff -u file.txt file2.txt
--- file.txt 2022-06-15 10:32:07.000000000 +0800
+++ file2.txt 2022-06-15 09:28:38.000000000 +0800
@@ -1,6 +1,4 @@
-a
b
c
-f
-g
-h
+d
+e
| 指示符 | 描述 |
|---|---|
| blank | 空白符表示上下文显示行,表示文本间相同的部分 |
| - | 删除行,表示第一个文件的内容 |
| + | 添加行,表示第二个文件的内容 |
| ! | 更改行,显示文本行的不同版本,出现在不同文件的各自部分 |
| 上下文模式和统一模式之间最显著的差异就是消除了重复上下文,所以简洁 |
diff -Naur old_file new_file > diff_fileold_file 和 new_file 要么是文件要么就是包含文件的目录。这个 r 选项支持递归目录树。一旦创建了 diff 文件,我们就能应用它,从而把旧文件替换为新文件:patch < diff_file就会把旧文件更新。# 我们创建了一个 diff 文件为 patchfile.txt
chappyzhao@ChappydeMacBook-Pro Pics % diff -Naur file.txt file2.txt > patchfile.txt
chappyzhao@ChappydeMacBook-Pro Pics % patch < patchfile.txt
patching file file.txt
chappyzhao@ChappydeMacBook-Pro Pics % cat file.txt
b
c
d
e
注意我们没有必要制定一个要修补的目标文件,因为 diff 文件(统一模式)已经在标题行中包含了文件名。一旦用了补丁我们就可以发现文件已经一致了。