Shell(五):文件的排序、合并和分割

  Linux文本处理命令是Shell编程中的常用命令,文本处理包含对文件记录的排序、文件的合并和分割等。

1、sort命令

  sort命令是一种对文件排序的工具,sort命令将输入文件看做由多条记录组成的数据流,而记录由可变宽度的字段组成,以换行符作为定界符。

  sort命令,可将记录分成多个域进行处理,默认的域分隔符是空格符,域分隔符可由用户指定其他符号。sort命令的基本格式为:

sort [选项] [输入文件]

  sort命令选项及其意义:

选项

含义

-c

测试文件是否已经排序

-k

指定排序的域

-m

合并两个已排序的文件

-n

根据数字大小进行排序

-o [输出文件]

将输出写到指定的文件,相当于将输出重定向到指定文件

-r

将排序结果逆向显示

-t

改变域分隔符

-u

去除结果中的重复行

1.1、sort命令的基本用法

1.1.1、-t 选项

  sort命令是分域对文件进行排序的,默认的域分隔符是空格符,-t选项可用于设置分隔符。

  对/etc/passwd文件进行排序:

  0

  /etc/passwd文件用冒号分隔域的,sort命令对/etc/passwd文件进行排序,用 -t 选项指定域分隔符为冒号,-t 与 ":" 之间没有空格。sort命令默认根据第1域对数据记录进行排序,若第1域相同,再根据第2域排序。

  当未指定 -t 时,分隔符是空格符,此时记录内开头与结尾的空格都将被忽略;当用 -t 选项改变分隔符时,空格符就有意义。

空格符:root:空格符

  对于上面的数据记录,若不指定 -t 选项,该记录了只有一个域,为 :root:,记录前后的空格符都被忽略;若用 -t 选项指定冒号,这条记录就包含了三个域,第1和3域是空格符,第2域是:root:。

1.1.2、-k 选项

  sort命令默认情况按第1域进行排序,也可按指定某个域进行排序,-k选项就是用于指定域的。

  sort命令以 1 表示第1域、以2表示第2域。

  0

  上例根据第5域对 /etc/passwd 进行排序。命令利用 -k5 指定了第3域。

1.1.3、-n 选项

  -n 选项可以指定根据数字大小进行排序,详情如下:

  0

  -n选项一般放在域号之后,-k3n就指定了以第3域排序,且不是按照第3与的字符串顺序排序,而是第3域的数字大小进行排序。

1.1.4、-r 选项

  -r 选项用于将排序结果逆向显示。

  0

  -n 选项默认是按从小到大排序,-r 选项将结果逆向显示。

1.1.5、 -u 选项

  -u 选项用于去除排除结果的重复行,若文件中有重复济洛路,可利用 -u 选项进行去重:

  0

1.1.6、-o 选项

  sort命令默认将排序后的结果输出到屏幕,若需要将结果保存到另一个文件中,可使用 -o 选项 加上文件名来完成。

  0

  将 /etc/passwd 按第3域的数值大小排序,并将排序结果存储到result.txt文件中,此时屏幕上不再显示任何信息。

  -o 选项与 Shell 提供的I/O重定向功能一样。

1.1.7、-c 选项

  -c 选项用于测试文件是否已经排好序:

  0

  测试result.txt是否按照默认方式排序,提示信息中包含了该文件中第1条未排序的记录。

  0

  测试result.txt文件是否按照第3域的数值大小排序,result.txt是按这种方式排好序的,Shell不提示任何信息。

1.1.8、-m 选项

  -m 选项用于将两个排好序的文件合并合成一个排好序的文件,在文件合并前,必须已经排好序。-m 选项对未排序的文件合并没有意义。

1.2、sort和awk的联合使用

  sort和awk都是分域处理文件的功能根据,结合起来可以有效的对文本块进行排序。

  文本块是由多行记录组合而成的数据块,PROFESSOR.txt 如下:

J Luo
Southeast University
Nanjing, China

Y zhang
Victory University
Melbourne, Australia

D Hou
Beijing University
Beijing, China

B Liu
Shanghai Jiaotong University
Beijing, China

C Lin
University of Toronto
Toronto, Canada

  PROFESSOR.txt中每个文件块记录了一位学者信息,由三行组成:第 1 行是姓名、第 2 行是学校名、第 3 行是学校所处的城市与国家。若需要根据姓名对文件块进行排序,结合 sort 和 awk 实现此功能。

0

  实现此功能的语句,由4条命令3个管道符组成。

cat PROFESSOR.txt | awk -v RS="" '{ gsub("\n","@");print }' | sort | awk -v ORS="\n\n" '{ gsub("@", "\n"); print }'

  cat命令将 PROFESSOR.txt 文件的内容作为第1条awk命令的输入数据;

  awk命令将每个文件块合并到一行,并用gsub函数将换行符替换成@符号,如将第一个文件块变为 "J Luo @Southeast University @Nanjing, China@";

  sort命令对这种格式的记录进行排序,默认以第1域排序,即按姓名的字母顺序,并将排序后的行作为第2条awk命令的输入数据;

  第2条awk命令执行与第1条awk相反的功能,将并为一行的数据重新划分为文件块输出,实现方法是用gusb函数将@符号替换成换行符。

2、uniq命令

2.1、uniq与sort -u的区别

  uniq命令用于去除文本文件的重复行,类似于 sort 命令的 -u 选项,两者区别如下:

  sort -u命令,所有重复的记录都能被去掉;

  uniq 命令,去除的重复行必须是连续重复出现的行,中间不能夹杂任何其他文件。

  0

  repeat.txt文件中的"this is a old content"记录先重复两次,隔开一行后,该行重复出现一次,用uniq命令去除repeat.txt文件重复行后,隔开的重复记录未被去除;而用sort -u 命令时,所有的重复记录了都被去掉。

2.2、uniq命令的选项

  uniq命令有3个选项,详情如下:

选项
含义
-c
打印每行在文本中重复出现的次数
-d
只显示有重复的记录,每个重复记录只出现一次
-u
只显示没有重复的记录

  uniq命令的-c选项打印每行在文本中重复出现的次数。

  0

  -d 选项用于显示有重复的记录,-u 选项显示没有重复的记录:

  0

  sort和uniq命令结合使用,统计一个文件内每种单词出现的次数,仙剑 count_word.sh,内容如下:

  新建count_word.sh脚本,内容如下:

 

#!/bin/bash
# count_word: 该脚本统计文件中单词出现的次数
ARGS=1
E_BADARGS=55
E_NOFILE=56

# 判断执行节本是否带了输入参数,即需要统计的文件名
# 若未带输入参数,返回 55 错误码
if [ $# -ne "$ARGS" ] 
then
    echo "Usage: 'basename $0' filename"
    exit $E_BADARGS
fi

# 判断当前目录下,输入的文件名是否存在
# 若文件不存在,则返回56错误码
if [ ! -f "$1" ]
then
    echo "File \"$1\" does not exists."
    exit $E_NOFILE
fi

# 统计文件单词数
# sed命令用于过滤句号、逗号、分号,也可加上其他需要过滤的符号
#sed命令第4个-e选项将单词间的空格转化为换行符
# sort对sed过滤后的结果排序,每行一个单词
# uniq -c 输出重复行出现的次数,sort -nr 按照出现频率从大到小排序
sed -e 's/\.//g' -e 's/\,//g' -e 's/\://g' -e 's/ /\n/g' "$1" | sort | uniq -c | sort -nr
exit 0

  count_word.sh脚本运行时加上一个参数,该参数表示待统计单词出现频率的文件名。

  第1个if/then结构,用于判断执行脚本时是否带了输入参数,若未带输入参数,返回55错误码;

  第2个if/then结构,用于判断在当前目录下,输入的文件名是否存在,若该文件不存在,返回56错误码;

  统计文件单词出现频率的命令,由sed、sort、uniq -c 和 sort -nr 四个命令组成,前面命令的输出作为后面命令的输入,sed命令的前三个-e选项 用于过滤句号、逗号、分号,可根据实际情况加上需要过滤的符号,sed命令的第4个 -e 选项将单词间的空格转化为换行符,将每个单词单独一行显示,便于sort命令排序。经过sed命令处理后,sort对行进行排序,同一个单词必定出现连续行,uniq -c输出重复行的次数,即该单词重复出现的次数。由于 uniq -c 的输出结果是"次数 单词"格式,sort -nr 对第 1 域(即单词出现的次数)进行排序,并倒置,使得出现次数多的单词排在最前面。

  执行结果如下:

  0

3、join命令

  join命令用于实现两个文件中记录的连接操作,将两个文件中具有相同域的记录选择出来,再将这些记录所有的域放到一行。

  新增 TEACHER.txt 文件,详情如下:

B Liu:Shanghai Jiaotong University:Shanghai:China
C Lin:University of Toronto:Toronto:Canada
D Hou:Beijing University:Beijing:China
Y Zhang:Victory University:Melbourne:Australia 

  新增 TEACHER_HOBBY.txt 文件,详情如下:

B Liu:Tea
C Lin:Song
J Cao:Pingpong
Q Cai:Shopping
Y Zhang:Photography
Z Wu:Chess

  连接 TEACHER.txt 和 TEACHER_HOBBY.txt 文件,详情如下:

  0

  两个文件已经是排好序了的,因为 join命令只能对 已排序 的文件进行操作。

3.1、命令选项

  join命令选项及其含义:

选项

含义

-a1 或 -a2

除了显示以共同域进行连接的结构外,-a1还显示第1个文件中没有共同域的记录,-a2表示显示第2个文件中没有共同域的记录。

-i

比较域内容时,忽略大小写差异

-o

设置结果显示的格式

-t

改变域分隔符

-v1 或 -v2

与 -a 选项类似,不显示以共同与进行连接的结果

-1 和 -2

-1 用于设置文件1用于连接的域,-2用于设置文件2用于连接的域

   join命令的基本语法为:

join [选项] 文件1 文件2

3.1.1、-a 和 -v 选项

  当两个文件进行连接时,两个文件的记录可能找不到共同域,join命令的结果默认是不显示这些未进行连接的记录。

  -a 和 -v 选项就是用于显示这个未进行连接的记录。-a1和-v1指显示文件1中未连接的记录,而 -a2 和 -v2 指显示文件2中未连接的记录。

  -a 和 -v 选项的区别在于:-a 选项显示以共同域进行连接的结果,而 -v 选项则不显示这些记录。

  0

  -a 选项 除了显示连接成功连接的记录之外,还分别显示 TEACHER.txt、TEACHER_HOBBY.txt中未进行连接的记录。

  

  -v 选项 只显示两个文件中未进行连接的记录。

3.1.2、-o 选项

  join命令默认显示连接记录在两个文件中的所有域,而且是按顺序来显示的。-o 选项用于改变结果显示的格式。

  

  "-o1.1 2.2 1.2",表示显示格式依次显示第1个文件中的第1个域,第2个文件的第2个域、第1个文件的第2个域。

3.1.3、-1 和 -2 选项

  join命令默认比较文件1和文件2的第1域,如果需要通过其他域进行连接,需要使用 -1 和 -2 选项,-1 用于设置文件1用于连接的域,-2 用于设置文件2用于连接的域。

  新建地区码文件 AREACODE.txt,存放城市及地区码 详情如下:

BEIJING:86010
HONGKONG:852
SHANGHAI:86021
TORONTO:001416

 TEACHER.txt 的第三域是城市名,为了将 TEACHER.txt 的城市名与 AREACODE.txt 的城市名进行连接,首先要将 TEACHER.txt 按城市名排序,并将排序结果保存到 TEACHER1.txt文件。

  0

  join命令使用"-1 3 -2 1"选项指定用于连接的域,"-1 3"表示文件1的第3域,"-2 1"表示文件2的第1域。

  由于AREACODE.txt的城市名是大写字母,因此,join带上 -i 选项表示在比较域时,忽略大小写,join的结果显示出城市名、姓名、学校、国家和地区码。

  若不对 TEACHER.txt 进行排序,直接进行join操作,join命令会出错,提示文件1未排序。

  0

  出现 TEACHER.txt 未排序的报错。

4、cut命令

  cut命令用于从标准输入或文本文件中按域或行提取文件,cut命令的基本格式为:

cut [选项] 文件

  cut命令选项及其意义列表如下:

选项

含义

-c

指定提取的字符数或字符返回

-f

指定提取的域数或域范围

-d

改变域分隔符

  cut命令的选项有三个,-c 用于按字符提取文件,-f用于按域提取文件,-d类似于 sort 和 join 命令的 -t 选项,用于改变域分隔符。

  0

  -c 后跟数字表示字符数或字符范围,共有三种表示方法:1、-cn 表示第n个字符;2、-cn,m表示第n个字符和第m个字符;3、-cn-m 表示第 n 个字符到 第 m 个 字符。

  由于 -c 选项是按字符提取文本的,因此无须使用 -d 改变域分隔符,但是,当使用 -f 域提取文本时,需要使用 -d 根据实际文本来设置域分隔符。

  0

  cut命令的 -f 选项按域提取TEACHER.txt文本,-f与-c选项一样,可使用三种方式指定域数或域范围,-f1-3 表示提取 TEACHER.txt的第 1 ~ 3 域。

5、paste 命令

  paste命令用于将文本文件或标准输出中的内容粘贴到新的文件,可以将来自不同文件的数据粘贴到一起,形成新的文件。paste命令的基本格式是:

paste [选项] 文件1 文件2

  paste命令有三个选项,详情如下:

选项

含义

-d

默认域分隔符是空格或Tab键,设置新的域分隔符

-s

将每个文件粘贴成一行

-

从标准输入中读取数据

  粘贴 file1 和 file2 详情如下:

  0

  -d 选项,指定分隔符,sort、join、cut命令改变域分隔符是为了按域读取文件内容,paste命令不同,改变域分隔符是用于设置输出文件的格式。

  0

  paste命令默认是将一个文件按列粘贴的,-s 选项可以实现将一个文件按行粘贴。

  0

  file1 和 file2 粘贴成新文件时,加上 -s 选项,FILE1内容被放到同一行,域之间以";"分隔,FILE2内容被粘贴到第2行同样以":"风格。

  paste不加 -s 选项时,文件内容按列输出,加上 -s 选项后,文件内容按行输出。

  paste命令的 "-" 选项较为特殊,当paste命令从标准输入中读取数据时,"-"选项才起作用。

  0

  paste命令通过读取ls命令的输出结果,再进行粘贴。paste命令后的 -d" " 将分隔符设置成空格符,在原本应出现 "文件1" 和 "文件2"的位置上加上"-" 选项,每行显示一个文件名,每个"-"选项表示读取1此标准输入数据,即读取到标准输入数据中的一个域。

6、split命令

  split命令用于将大文件切割成小文件,split命令可以按照文件的行数、字节数切割文件,并能在输出的多个小文件中自动加上标号。

  split命令的基本格式如下:

split [选项] 待切割的大文件 输出的小文件

  split命令的选项用于指定切割的依据,将split命令的选项显示如下:

选项

含义

-或-1

指定切割成小文件的行数

-b

指定切割成小文件的字节

-C

切割时尽量维持每行的完整性

  分隔大文件为小文件,详情如下:

  0

  split命令利用 -2 自定按2行对TEACHER.txt进行切割,即每2行记录切割成1个文件。small.txt为指定输出小文件名,split命令在small.txt后面自动加上编号以区分不同的小文件,编号aa~zz,即第1个小文件是 small.txtaa,第2个是small.txtab.

  -b 和 -C 选项都是用于指定小文件的字节数,两个选项都是按照文件大小来切割文件,详情如下:

  0

  使用 ll 命令查看 TEACHER.txt 文件的大小,大小为180B,将 TEACHER.txt 按每100B切割成小文件,为指定小文件的名称,就以 x 加上 aa~zz的编号命令。

  查看切割的小文件时,发现内容不完整,split命令-b选项在切割文件时仅考虑了文件大小,未考虑记录的完整性。

  使用 -C 选项进行切割,详情如下:

  0

  利用 -C 选项按 90B 切割TEACHER.txt文件,得到三个小文件,但是 xaa 是 50B,xab 是 80B,xac是 47B,xaa、xab、xac者三个文件存放了完整的记录。

  -C选项并不严格按照 90B 大小进行切割,而是在切割时尽量维持每行的完整性。

7、tr命令

  tr命令实现字符转换功能,类似于sed命令,tr命令比sed命令简单,tr命令能实现的功能,sed命令都可以实现。

tr [选项] 字符串1 字符串2 <输入文件

  tr命令有三个选项,tr命令可以跟两个字符串,大多数情况下,只能跟一个字符串。"<输入文件"表示将输入文件重定向到标准输入,tr命令与sort、uniq、join命令不同,只能从标准输入读取数据。

  tr命令要么将输入文件重定向到标准输入,要么从管道读入数据。

选项

含义

-c

选定字符串1中字符集的补集,反选字符串1中的字符集

-d

删除字符串1中出现的所有字符

-s

删除所有重复出现的字符序列,只保留一个


  tr命令的 -d 选项只需要跟一个字符串,表示删除字符串中出现的所有字符:

  0

  -s 选项用于删除所有重复出现的字符序列,只保留一个,即将重复出现的字符串压缩为一个字符。

  0

  AREACODE.txt文件包含若干空白行,空白行可看做改行只有一个换行符,无其他任何字符。只要将重复出现的换行符压缩成一个就可消除空白行。

  0

  tr命令加上字符串1和字符串2,将字符串1用字符串2来替换。如上将 大写字母换成小写字母。

8、tar命令

  tar命令是Linux的归档命令,tar命令实现了Linux系统文件的压缩和解压缩。

  tar命令的基本格式:

tar [选项] 文件名或目录名

  tar的常用选项如下:

选项

含义

-c

创建新的包

-r

为包添加新的文件

-t

列出包内容

-u

更新包中的文件,若包中无此文件,则将该文件添加到包中

-x

解压缩文件

-f

使用压缩文件或设备,该选项通常是必选的

-v

详细报告tar处理文件的信息

-z

用gzip压缩和解压缩文件,若加上此选项创建压缩包,解压缩时也需要加上此选项

  tar命令压缩文件和查看压缩包文件详情:

  0

  -r 选项,向压缩包添加文件:

  0

  tar命令中拥有解压缩功能,解压通用命令:

tar -xvf 压缩包名称
tar -zxvf 压缩包名称

  加上 -z 选项可以解压用 gzip 压缩的文件,不加 -z 选项解压非 gzip 压缩的文件。-x 选项表示解压缩文件, -v 选项能生成解压缩过程的状态信息, -f 选项时必选选项。

  0

  利用tar命令解压file.all包,由于file.all非gzip格式,当加上-z选项时,解压出错,去掉 -z 选项解压成功,因-v 选项的存在,tar命令自动生成被解压出的文件信息。

  tar -cf 命令创建的包,实际上是将多个文件放到一起,此时文件并没有被压缩,gzip命令是Linux系统中常用的压缩工具,可以对tar命令创建的包进行压缩。

  0

  gzip命令压缩file.all包,生成名为file.all.gz的文件,file.all.gz和file.all的内容是一样的,但file.all.gz文件经过了压缩,占用空间比较小。

  由于file.all.gz是gzip格式的压缩文件,利用tar命令进行解压时,需添加 -z 选项。

  gzip命令可将file.all.gz还原到file.all文件,只要在gzip命令后面加上-d选项即可。

0

9、总结

  sort命令是一种文本排序工具

  uniq命令可去除文本的重复记录,而且可以统计重=重复文本行的数量

  join命令实现类似于关系数据库中的连接操作

  cut命令用于从标准输入或文本文件中按域或行提取文本

  paste命令用于将多个文本文件或标准输出中的内容粘贴而形成新的文件

  split命令用于将大文件切割成小文件

  tr命令实现字符转换功能,可以实现文本文件的过滤功能

  tar命令是Linux的归档命令,tar命令和gzip命令用于实现Linux系统文件的压缩和解压缩。

 

posted @ 2023-10-12 21:03  无虑的小猪  阅读(1672)  评论(0编辑  收藏  举报