Linux 命令行——文本处理命令:cat、sort、uniq、cut、comm、diff、patch

文本处理

      • 1. 文本处理
      • 2. 文本应用程序
      • 3. 比较文本

本文摘录自 Linux 命令行

1. 文本处理

所有类 Unix 操作系统都严重依赖于几种数据存储的文本文件。所以,有许多用于文本处理的工具。

2. 文本应用程序

目前为止,我们已经知道了 nano 和 vim,看过一堆配置文件。文本功能很强大,我们写作用的文档、网页、email、程序源码等都是文本的格式。

  1. cat—链接文件并打印到标准输出。cat -A foo.txt会显示文本和非打印字符,如 tab 和空格。cat 也有用来矫正文本的选项,最常用的是 -n(给文本行添加行号)和 -s(禁止输出多个空白行):cat -ns foo.txt
  2. sort—给文本行排序.这个 sort 对标准输入的文本、一个或多个文件进行排序,然后输出到标准输出。不会对原文件产生影响
# 输入命令后,我们输入 '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
...
  1. uniq—报告或者省略重复行。它是一个轻量级程序。当给一个排好序的文件(包括标准输出),uniq 会删除任意重复行,并把结果发送到标准输出。它常常和 sort 一起使用。
# 创建文件
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

  1. cut—从文件的每行删除字段
  2. paste—合并文件文本行
  3. join—基于某个共享字段来联合两个文本文件

3. 比较文本

通常文本的不同版本比较是很有用的,尤其是对于系统管理员和软件开发人员,如管理员可能会拿现有的配置文件与之前的版本做比较来查找一个错误,而程序员需要经常查看程序的修改。

  1. comm—逐行比较两个有序的文件,并且会显示每个文件特有和共有的文本行。但是当找到第一行共有行即使后面有相同行但是顺序是不一致的也不会出现在共有行下,这也是要求有序的原因。
# 创建两个准备文件
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
  1. diff—逐行比较文件,类似于 comm 程序,diff 程序被用来监测文件之间的差异。diff 更复杂,它支持许多输出格式和一次性处理更大文本集合的能力。程序员经常使用 diff 程序来检查不同程序源码的版本更改,diff 能递归的检查源码目录树。diff 经常用来创建一个 diff 文件或者补丁,通过 patch(补丁)命令,可以把文件从一个版本替换到另一个版本。
# 可以看到 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 空白符表示上下文显示行,表示文本间相同的部分
- 删除行,表示第一个文件的内容
+ 添加行,表示第二个文件的内容
! 更改行,显示文本行的不同版本,出现在不同文件的各自部分
上下文模式和统一模式之间最显著的差异就是消除了重复上下文,所以简洁
  1. patch—给原始文件打补丁,用来把更改应用到文本文件中。它接受 diff 程序的输出,通常用来更新版本。我们考虑一个很著名的问题,Linux 内核是由一个大型的,组织松散的贡献者团队开发而成,他们通常固定提交少量代码。Linux 内核由几百万行代码组成,尽管每个人每次做的更改很少,每次小的改动不值得进行一次版本更新,所以每次贡献者只需一起提交 diff 文件。一个 diff 文件包含先前的内核版本与带有贡献者修改的新版本之间的差异。然后其他接收者使用 patch 程序就可以把这些更改应用到他的内核源码树中。使用 diff/patch 组合有两个重大好处:1. 与整个内核源码树的大小相比一个 diff 文件非常小,2. 一个 diff 文件可以简洁地显示所做的修改,从而允许程序补丁的审阅者快速评估它。
    1. GNU 文档建议这样使用 diff 命令: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 文件(统一模式)已经在标题行中包含了文件名。一旦用了补丁我们就可以发现文件已经一致了。

你可能感兴趣的:(linux,linux,运维,服务器)