Linux之文本处理---cat、sort、uniq、cut、paste、join、comm、diff、patch、tr、sed、aspell

由于所有类UNIX操作系统都严重依赖于文本文件来进行某些数据类型的存储,所以需要很多可以进行文本操作的工具.
常见的文本格式有

  • 文件:使用纯文本格式编辑的文件。在使用文本格式编辑较大文件时,常用的方法是,首先在文本编辑器中编辑大型文档的内容,然后使用标记语言描述文件格式。
  • 网页:网页属于文本文档,一般使用HTML(Hypertext Markup Language)或XML(eXtensible Markup Language)等标记语言描述内容的可视化.
  • 电子邮件:电子邮件本质上是一种基于文本的媒介,即便是非文本附件,在传输时候也会转为文本格式.
  • 打印机输出:在类UNIX系统中,准备向打印机传送的信息是以纯文本格式传送的。如果该页包含图像,则将其转换成PostScript文本格式页面描述语言再送至指定程序并打印图像像素.
  • 程序源代码:类UNIX很多命令行是为了支持系统管理软件开发。所有的软件都是从文本开始,源代码总是以文本形式编辑.

0.参考文献

《Linux命令行大全》 [美] William E. Shotts. Jr 著 郭光伟 郝记生 译, 人民邮电出版社

如有侵权,可联系博主删除.
更多有用的Linux知识详解,可参考我的Linux学习导航页

1. cat—进行文本之间的拼接并且输出到标准格式

cat我们已经在Linux命令行I/O重定向—重定向操作符、cat、管道、sort、uniq、wc、grep、head、tail、tee中讲过基本用法,下面补充三个常用的选项.
-A选项用于显示文本中的非打印字符,例如一些控制字符—(制表符和空格),另一种常见情况是文件中包含末尾带有空格的文本行.
例如,输入制表符+The qucik brown fox jumped over the lazy dog. 按下Ctrl+D结束的如下命令

$ cat > foo.txt
        The qucik brown fox jumped over the lazy dog.

得到一个以制表符开头、空格符结尾的文本行.

$ cat -A foo.txt
^IThe qucik brown fox jumped over the lazy dog.$

文本中的Tab制表符由符号"^I“表示,意思是"Ctrl+I”.在文件末尾出现的"$"符说明行末尾存在空格.
-n选项用于对行编号,’-s’选项用于禁止输出多个空白行.

2. sort—对文本行进行排序

sort是一个排序程序.

$ sort > foo.txt
c
b
a
$ sort foo.txt
a
b
c

sort允许多个文件作为其参数,可以将多个文件融合成一个已经排序的整体文件。

$ sort file1.txt file2.txt file3.txt > final_sorted_list.txt

以上将三个文本文件拼接成一个已经排序好的整体文件.
表1 常见的sort选项

选项全局选项表示描述
-b–ignore-leading-blanks默认情况下,整个行都会进行排序操作,也就是从行的第一个字符开始.添加该选项后,sort会忽略行开头的空格,并且从第一个非空白字符开始排序.
-f–ignore-case排序时不区分大小写
-n–numeric-sort基于字符串的长度进行排序.该选项使文件按数值顺序而不是按字母表顺序进行排序.
-r–reverse逆序排序
-k–key=field1[,filed2]对field1与field2之间的字符排序,而不是整个文本行.
-m–merge一个排好序的文件,而不执行额外的排序操作
-o–output=file将排序结果输出到文件而不是标准输出
-t–field-separator=char定义字段分隔符.默认情况下,字段是由空格或制表符分开的

作为例子,我们给出使用du命令+sort命令输出home目录下前10个文件或目录占用空间最大的文件.

$ du -sh ~/* | head
16K     /home/lmj/6.15
19G     /home/lmj/anaconda3
13M     /home/lmj/anything
29M     /home/lmj/apex
16K     /home/lmj/bak.bashrc.swp
19M     /home/lmj/cocoapi
27M     /home/lmj/code_faster
349M    /home/lmj/code_tx2
809M    /home/lmj/crawler
307M    /home/lmj/data

我们可以使用sort -n选项,对其所有空间占用进行排序,这里使用了-r进行了逆序排序,即从大到小.

$ du -sh ~/* | sort -nr | head
809M    /home/lmj/crawler
445M    /home/lmj/trt_maskrcnn
412K    /home/lmj/sampleUffMaskRCNN
396K    /home/lmj/face_detect_demo
349M    /home/lmj/code_tx2
313M    /home/lmj/DeepFashion
307M    /home/lmj/data
225M    /home/lmj/log
199M    /home/lmj/ubuntu18
172K    /home/lmj/sampleFasterRCNN

但是这种排序仅仅对数值出现在第一行的开头有效.如果使用ls -l命令呢?

$ ls -l ~/ | head
total 48112
total 48112
drwxrwxr-x  2 lmj lmj     4096 Jun 15 14:06 6.15
drwxrwxr-x 26 lmj lmj     4096 Apr 22 12:17 anaconda3
drwxrwxr-x  2 lmj lmj     4096 Feb 25 15:16 anything
drwxrwxr-x 11 lmj lmj     4096 Sep 25  2019 apex
-rw-r--r--  1 lmj lmj    16384 Apr  3 10:01 bak.bashrc.swp
drwxrwxr-x  8 lmj lmj     4096 Dec  4  2019 cocoapi
drwxrwxrwx 10 lmj lmj     4096 Dec  7  2019 code_faster
drwxrwxr-x 10 lmj lmj     4096 May  3 15:37 code_tx2
drwxrwxr-x  5 lmj lmj     4096 Apr 14  2019 crawler

此时,可以用-k选项

$ ls -l ~/ | sort -nr -k 5| head

3. uniq–通知或省略重复的行

给定一个已经排序好的文件(包括标准输入)后,uniq会删除任何重复的行并将结果输出到标准输出中.它通常用sort结合以删除sort输出内容出重复的行.
简单的例子

$ cat > foo.txt
a
b
c
a
b
c

因为uniq 只对排好序的文本才有作用,因此直接使用没有任何效果.

$ sort foo.txt | uniq
a
b
c

表2 常见的uniq选项

选项功能描述
-c输出重复列表,并且重复行前面加上其出现次数
-d只输出重复行,但不包括单独行
-f n忽略每行前n个字段
-i行与行之间比较时忽略大小写
-s n跳过每行的前n个字符
-u仅输出不重复的行,为默认选项

例如

$ sort foo.txt | uniq -c
      2 a
      2 b
      2 c

4. cut—删除文本行中部分内容

cut命令用于从文本行中提取一段文字并将其输出至标准输出。
表3 cut选择选项

选项功能描述
-c char_list从文本行中提取char_list定义的部分内容
-f field_list从文本行中提取field_list定义的一个或多个字段
-d delim_char指定-f选项后,使用delim_char作为字段分界符号,默认为单个Tab制表符
–complement从文本中提取整行,除了那些由-c和/或-f指定的部分

简单的例子

$ cut -f 3 foo.txt

用于切出foo.txt中每行以制表符为分隔符的第三个字段.
例如此时我们切割出的格式为

06/01/2006
10/30/2008
03/20/2006

进一步我们可以把年份切割出来

$ cut -f 3 foo.txt | cut -c 7-10

因为固定第7-10个字符表示的是年份.
以下例子展示指定费Tab字符为制表符,从/etc/passwd文件中提取每行的第一个字符

$ cut -d ":" -f 1 /etc/passwd | head
root
daemon
bin
sys
sync
games
man
lp
mail
news

5. paste—合并文本行

pastecut逆操作.它向文件中增加一个或是更多的文本列.该命令读取多个文件并将每个文件中提取出的字段结合为一个整体的标准输出流.
例如对于两个行数相同,且信息对应的文件 distros-dates.txt和distros-versions.txt,可以使用paste将各个参数按照指定顺序进行排列.

$ paste distros-dates.txt distros-versions.txt

6. join—连接两个文件中具有相同字段的行

joinpaste相似,都是向文件添加列信息.不同的是,其通常与“关联数据库”联系在一起,它是一个基于共享数据库中把共享关键字段多个表格的数据组合成一个期望结果。
命令使用与patse类似,例如对于两个存在首列共享字段的文件,且按照关键字段排好序,则可以使用

$ join distros-dates.txt distros-versions.txt

7. comm–逐行比较两个已排序文件

comm命令一般用于文本文件之间的比较,显示两文件中相异的行以及相同的行.
首先,产生两个相近的文件

$ cat > file1.txt
a
b
c
d
$ cat > file2.txt
b
c
d
e

使用comm比较文件差异

$ comm file1.txt file2.txt
a
                b
                c
                d
        e

comm输出三列内容,第一列显示第一个文件独有的行,第二列显示第二个文件独有的行,第三列显示两个文件共有的行。
comm还支持-n参数,可以省略输出第n列的内容.

8. diff—逐行比较文件

diff功能与comm类似,但是更复杂,支持多种输出格式,并且具备一次性处理大文件集的能力。diff通常被软件开发者用于检查不同版本的源代码之间的差异,因为其能递归检查源代码目录(通常称为源树).diff常见用法就是创建diff文件和布丁。

$ diff file1.txt file2.txt
1d0
< a
4a4
> e

默认形式的输出结果实际上是对两者文件差异的一个简洁描述.每一组改动的前面都有一个以“范围 执行操作 范围”形式(range operation range)表示的改变操作命令,该命令会告诉程序对第一个文件的某个位置进行某种改变,便可实现与第二个文件内容一致.diff改变命令如下表.
表20-4 diff改变命令

改变操作功能描述
r1ar2将第二个文件中r2位置的行添加到第一个文件中的位置r1处
r1cr2用第二个文件r2处的行代替第一个文件r1处的行
r1dr2删除第一个文件r1处的行,并且删除的内容作为第二个文件r2行范围的内容

默认格式并没有其它格式的应用广泛,上下文格式统一格式才是比较常用的格式.
上下文格式的输出结果

$diff -c file1.txt file2.txt
*** file1.txt   2020-06-22 11:20:05.940633105 +0800
--- file2.txt   2020-06-22 11:20:19.641086025 +0800
***************
*** 1,4 ****
- a
  b
  c
  d
--- 1,4 ----
  b
  c
  d
+ e

该结果以两个文件的名字和时间信息为开头,第一个文件用星号表示,第二个文件用破折号表示.输出结果的其余部分出现的星号和破折号则分别表示各自所代表的文件.其它内容便是两个文件之间的差异组,包括文件的默认行号.第一组差异,以*** 1,4 ****开头,表示一个文件的第1行到第4行;第二组便以--- 1,4 ----,表示第二个文件的第1行到第4行,每个差异行都是以如下四个标识符之一开头.
表5 diff上下文格式差异标识符

标识符含义
(无)该行表示上下文文本,表示两个文件共有的行
-缺少的行,表示该行仅在第一个文件中出现,第二个文件中则没有
+多余的行,表示该行仅在第二个文件中出现,第一个文件中没有
!改变的行.两个版本的行内容都会显示出来,每一个都各自出现在差异组中相应部分

统一格式与上下文格式相似但是更简明,此格式用-u选项指定.

$ diff -u file1.txt file2.txt
--- file1.txt   2020-06-22 11:20:05.940633105 +0800
+++ file2.txt   2020-06-22 11:20:19.641086025 +0800
@@ -1,4 +1,4 @@
-a
 b
 c
 d
+e

统一格式与上下文格式最显著的区别是,统一格式没有重复的文本行.@@ -1,4 +1,4 @@字符串表示差异组描述的两个文件各自的行范围.之后每一行都以下面三种可能的标识符开头.
表6 diff统一格式的差异标识符

字符含义
(无)两个文件共有的行
-相对于第二个文件而言,,第一个文件中没有的行
+第一个文件多余的行

9. patch—对原文件进行diff操作

patch命令用于更新文本文件.它利用diff命令的输出结果将较旧版本的文件升级成较新版本.例如在Linux内核几百万行的代码中,每个开发者仅负责小部分,对每位开发者而言,每对代码改动一次就得向其他开发者发送整个内核源代码不切实际,实际上,一般只要发送diff补丁文件即可.diff/path主要有如下优点

  • 与源代码树大小相比,diff文件很小
  • diff文件非常简洁地描述了文件所做的改变,便于补丁的接收者快速对其评价
    生成供patch使用的diff文件,GNU文件系统建议采用如下方式:
diff -Naur old_file new_file > diff_file

此处old_file既可以是单独的文件也可以是包含文件的目录,使用-r参数是为了进行递归目录树搜索.
一旦创建了diff文件,便可以将其用于修补原文件old_file,从而升级为新文件new_file.

$ diff -Naur file1.txt file2.txt > patchfile.txt
$ patch < patchfile.txt
patching file file1.txt
$ cat file1.txt
b
c
d
e

10.tr—替换或删除字符(非交互式)

之前描述的文本编辑大多是交互式的,也就是说只要手动移动鼠标然后输入需要进行的改变.然而,也可以进行非交互的方式进行文本编辑.
tr是替换字符命令,可以将其看做基于字符的查找和替换操作.
下例是使用tr进行大小写字母替换的例子

$ echo "lowercase letters" | tr a-z A-Z
LOWERCASE LETTERS

也就是说,tr可以对标准输入进行操作并且将结果以标准形式输出.tr有两个参数:等待转换的字符集和与之对应的替换字符集.字符集的表示方式有

  • 枚举列表:例如,ABCDEFGHIJKLMNOPQRSTUVWXYZ
  • 字符范围:例如,A-Z
  • POSIX字符类:例如[:upper:].

多数情况下,两个字符集应该是同等长度;然而,第一个字符集比第二个字符集长也是有可能的,例如

$ echo "lowercase letters" | tr [:lower:] A
AAAAAAAAA AAAAAAA

tr还有个有趣的用法,使用-s选项,可以“挤兑”(删除)重复出现的字符,示例如下

$ $ echo "aabbcc" | tr -s ab
abcc

请注意,重复的字符必须是毗邻的,否则不起作用

11. sed—用于文本过滤和转换的流编辑器

sed是stream editor(流式编辑器)的缩写,它可以对文本流、指定文件集或标准输入进行文本编辑.
sed的用法,总的来说,首先给定sed某个简单的编辑命令(在文本行中)或是包含多个命令的脚本文件名,然后sed便对文本流的内容执行给定的编辑命令.例如

$ echo "front" | sed "s/front/back/"
back

首先echo生成了只包含一个单词的文本流,然后将该文本流叫给sed处理,而sed对其执行s/front/back/指令,最后输出"back".可以认为这里sed与vi中的替换命令相似.
sed的命令以单个字母开头,上个例子中,以字母s表示替代,气候紧跟替换字符,替换字符由分界符的斜线字符分开.分界符选择任意,习惯上使用斜线.
sed中国的多数命令允许在其前添加一个地址,该地址用来指定输入流的哪一行被编辑.如果地址省略,则默认对第一行编辑.最简单的地址就是行号.

$ echo "front" | sed "1s/front/back/"
back

表7 sed地址表示法

地址功能说明
Nn是正整数表示行号
$最后一行
/regexp/用POSIX基本表达式描述的行
addr1,addr2行范围,从addr1至addr2的所有行
first~step代表从行号为first开始,以step为间隔的所有行.例如1~2为所有奇数行
addr1,+naddr1行及其之后的n行
addr!除了addr行之外的所有行,addr可以是以上任意表示形式

例如

$ sed -n '1,5p' distros.txt

p命令代表输出指定行,这里输出了第1行到第5行,-n选项是不会自动打印选项,以防sed会默认输出每一行内容.

$ sed -n '/SUSE/p' distros.txt

以上是使用正则表达式搜索匹配道SUSE的行.
我们已经学了s和p选项,sed更完整的基本编辑指令如下
表8 sed基本编辑指令表

命令功能描述
=输出当前行号
a在当前行后附加文本
d删除当前行
i在当前行前输入文本
p打印当前行.默认情况下,sed会输出每一行并且只编辑文件内那些匹配指定地址的行,使用-n选项后,默认操作被覆盖.
q退出sed不再处理其他行,如果没有指定-n选项,就会输出当前行
Q直接退出sed不再处理行
s/regexp/replacement/将regexp的内容替换为replacement代表的内容
y/set1/set2将字符集set1转换为字符集set2,与tr不同,sed要求这两个字符集等长.

12 aspell—交互式拼写检查工具

检查一篇简单散文的拼写错误,可以用如下方式

aspell check textfile

其检验模式是与用户交互的,被怀疑的错误字符以高亮显示,0~9显示拼写建议,还有一些其它操作.
首先,创建含拼写错误的txt,然后检查它

$ cat > foo.txt
The quick brown jimped over the laxy dog
$ aspell check foo.txt
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值