您的位置:首页 > 运维架构 > Shell

shell快速排序、去重文本内容

2014-10-14 17:20 197 查看
逛ChinaUnix论坛,常常可看到到日经帖,怎么快速排序一个文本内容,或者计算某行出现次数。这些问 题大部分都可以通过简单的sort、uniq命令来解决。
首先准备两个文本
cat file1:Boys in Company C :HK :192 :2192Alien :HK :119 :1982The Hill :KL :63 :2972Aliens :HK :532 :4892Star Wars :HK :301 :4102A Few Good Men :KL :445 :5851Toy Story :HK :239 :3972cat file2:
boy took bat home
boy took bat home
girl took bat home
boy took bat home
boy took bat home
dog brought hat home
dog brought hat home
dog brought hat home

sort:
将文件的每一行作为一个单位,相互比较,比较原则是从首字符向后,依次按ASCII码值进行比较,最后将他们按升序输出。

常用的几个参数: sort -mnrtku
m:合并文件
n:按数值大小来排序
r:逆序排
t:自定义分隔符来划分域
k:选定域来排序
u:全文本去重
域相当于列
1、sort -m file1 file2 合并两个文件
Boys in Company C :HK :192 :2192

Alien :HK :119 :1982
boy :took :bat :home
boy :took :bat :home
girl :took :bat :home
boy :took :bat :home
boy :took :bat :home
dog :brought :hat :home
dog :brought :hat :home
dog :brought :hat :home
The Hill :KL :63 :2972
Aliens :HK :532 :4892
Star Wars :HK :301 :4102
A Few Good Men :KL :445 :5851
Toy Story :HK :239 :3972
2、-n参数是有时候会排序出现10比2小的情况,因为sort是直接比较第一个字符,所以要使用-n来进行数值比较。
3、-r参数,sort排序小的排上,大的在下,有时候行数很多,你只想知道最大的就可以sort -r |more就可以了。
4、-t参数,选定分隔域符号,这个常常和-k参数一起用,如我们需要按file1的第三列的数值大小排序
sort -n -t:-k3 file1
The Hill :KL :63 :2972
Alien :HK :119 :1982
Boys in Company C :HK :192 :2192
Toy Story :HK :239 :3972
Star Wars :HK :301 :4102
A Few Good Men :KL :445 :5851
Aliens :HK :532 :4892
如果不加-n参数:

sort -t: -k3 file1
Alien :HK :119 :1982
Boys in Company C :HK :192 :2192
Toy Story :HK :239 :3972
Star Wars :HK :301 :4102
A Few Good Men :KL :445 :5851
Aliens :HK :532 :4892
The Hill :KL :63 :2972
隐藏属性,sort的输出都是标准屏幕输出,如果我们要输出到源文件,使用重定向就会杯具。。

sort file1>file1;cat file1,你会得到一个空文件。这时候要使用-o参数来实现这个功能。
sort file1 -o file1

uniq:
这个命令读取输入文件,并比较相邻的行。在正常情况下,第二个及以后更多个重复行将被删去,行比较是根据所用字符集的排序序列进行的。该命令加工后的结果写到输出文件中。输入文件和输出文件必须不同。如果输入文件用“- ”表示,则从标准输入读取。
它与sort -u的区别在于,sort -u是全文本去重,而uniq是比较相邻行,将第二个及以后更多重复行删去。

语法:uniq [-cdu][-f<栏位>][-s<字符位置>][-w<字符位置>][--help][--version][输入文件][输出文件]
补充说明:uniq可检查文本文件中重复出现的行列。
参数:
-c或--count 在每列旁边显示该行重复出现的次数。
-d或--repeated 仅显示重复出现的行列。
-f<栏位>或--skip-fields=<栏位> 忽略比较指定的栏位。
-s<字符位置>或--skip-chars=<字符位置> 忽略比较指定的字符。
-u或--unique 仅显示出一次的行列。
-w<字符位置>或--check-chars=<字符位置> 指定要比较的字符。
--help 显示帮助。
--version 显示版本信息。
常用的是-c参数,显示行的重复出现次数。

uniq -c file2
2 boy :took :bat :home
1 girl :took :bat :home
2 boy :took :bat :home
3 dog :brought :hat :home
但由于是只比较相邻行,所以还是配合sort先排序一下:

sort file2 |uniq -c
4 boy :took :bat :home
3 dog :brought :hat :home
1 girl :took :bat :home
这样才得到我们想要的结果。

最后再把这两个文件合并的漂亮一点:
sort -m file1 file2 |sort |uniq -c |sed 's/ //g'|awk -F ":" '{printf ("%-10s %10s %10s %10s\n",$1,$2,$3,$4)}'
1AFewGoodMen KL 445 5851
1Alien HK 119 1982
1Aliens HK 532 4892
1BoysinCompanyC HK 192 2192
4boy took bat home
3dog brought hat home
1girl took bat home
1StarWars HK 301 4102
1TheHill KL 63 2972
1ToyStory HK 239 3972
感觉还是很坑爹。。
1、sort -m居然只合并,没有排序
2、printf的对齐,看上去这么怪。。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  linux sort uniq