yyyyyyyyyyyyyyyyyyyy

博客园 首页 新随笔 联系 订阅 管理

sort

sort 命令对 File 参数指定的文件中的行排序,并将结果写到标准输出。如果 File 参数指定多个文件,那么 sort 命令将这些文件连接起来,并当作一个文件进行排序。

sort语法

 
[root@www ~]# sort [-fbMnrtuk] [file or stdin]
选项与参数:
-f  :忽略大小写的差异,例如 A 与 a 视为编码相同;
-b  :忽略最前面的空格符部分;
-M  :以月份的名字来排序,例如 JAN, DEC 等等的排序方法;
-n  :使用『纯数字』进行排序(默认是以文字型态来排序的);
-r  :反向排序;
-u  :就是 uniq ,相同的数据中,仅出现一行代表;
-t  :字段之间的分隔符默认是空格,如果让\t作为分隔符,需要转义:-t $'\t';
-k  :以那个区间 (field) 来进行排序的意思
 

对/etc/passwd 的账号进行排序
[root@www ~]# cat /etc/passwd | sort
adm:x:3:4:adm:/var/adm:/sbin/nologin
apache:x:48:48:Apache:/var/www:/sbin/nologin
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin

sort 是默认以第一个数据来排序,而且默认是以字符串形式来排序,所以由字母 a 开始升序排序。

 

/etc/passwd 内容是以 : 来分隔的,我想以第三栏来排序,该如何

[root@www ~]# cat /etc/passwd | sort -t ':' -k 3
root:x:0:0:root:/root:/bin/bash
uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
bin:x:1:1:bin:/bin:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin

默认是以字符串来排序的,如果想要使用数字排序:

cat /etc/passwd | sort -t ':' -k 3n
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/bin/sh
bin:x:2:2:bin:/bin:/bin/sh

默认是升序排序,如果要倒序排序,如下

cat /etc/passwd | sort -t ':' -k 3nr
nobody:x:65534:65534:nobody:/nonexistent:/bin/sh
ntp:x:106:113::/home/ntp:/bin/false
messagebus:x:105:109::/var/run/dbus:/bin/false
sshd:x:104:65534::/var/run/sshd:/usr/sbin/nologin

 

如果要对/etc/passwd,先以第六个域的第2个字符到第4个字符进行正向排序,再基于第一个域进行反向排序。

cat /etc/passwd |  sort -t':' -k 6.2,6.4 -k 1r      
sync:x:4:65534:sync:/bin:/bin/sync
proxy:x:13:13:proxy:/bin:/bin/sh
bin:x:2:2:bin:/bin:/bin/sh
sys:x:3:3:sys:/dev:/bin/sh


查看/etc/passwd有多少个shell:对/etc/passwd的第七个域进行排序,然后去重:

cat /etc/passwd |  sort -t':' -k 7 -u
root:x:0:0:root:/root:/bin/bash
syslog:x:101:102::/home/syslog:/bin/false
daemon:x:1:1:daemon:/usr/sbin:/bin/sh
sync:x:4:65534:sync:/bin:/bin/sync
sshd:x:104:65534::/var/run/sshd:/usr/sbin/nologin

 

按指定字段进去重:

sort -t "^" -k 8 -su 29w.csv >278422.csv

分割符为"^",按第8列排序,-su为去重。 

 

mac上出现中文失效:Set LC_ALL=C 

 

ls给文件名中数字排序

事情是这样的
想用这种语句for file in `ls /TEST/`按文件名次序调用文件。
可是结果不是
[root@localhost TEST]# ls
expe expe14 expe2 expe25 expe30 expe36 expe41 expe47 expe52 expe58
expe1 expe15 expe20 expe26 expe31 expe37 expe42 expe48 expe53 expe59
expe10 expe16 expe21 expe27 expe32 expe38 expe43 expe49 expe54 expe6
expe11 expe17 expe22 expe28 expe33 expe39 expe44 expe5 expe55 expe7
expe12 expe18 expe23 expe29 expe34 expe4 expe45 expe50 expe56 expe8
expe13 expe19 expe24 expe3 expe35 expe40 expe46 expe51 expe57 expe9

ls expe* |sort -k1.5n
expe1
expe2
expe3
expe4
expe5
expe6
expe7
expe8
expe9
expe10
expe11
expe100

-k1.5表示第一个字段、第5个字符开始:

KEYDEF is F[.C][OPTS][,F[.C][OPTS]] for start and stop position, where
F is a field number and C a character position in the field; both are
origin 1, and the stop position defaults to the line's end. If neither
-t nor -b is in effect, characters in a field are counted from the
beginning of the preceding whitespace. OPTS is one or more single-let‐
ter ordering options [bdfgiMhnRrV], which override global ordering
options for that key. If no key is given, use the entire line as the
key.

 
 
 

让tab作为分隔符,这个时候你可以转义tab:

$sort -t '\t' -k3n a.txt >a.sort

sort: multi-character tab `\t'  (出错)

这个不能按照tab分隔符进行字段排序,换成如下两种方式就可以了

$ sort  -t $'\t' -k3n a.txt>a.sort2,

$ sort -t'<ctrl>v<tab>' -k3,3n a.txt>a.sort

<ctrl>v<tab>代表先同时按下Ctrl和v键,然后松开,按下tab键。

 
 
汉字sort排序,要设置:LANG=GBK
 
 
 
 
 
 
 sort命令的k选项大讨论

[正文开始]
有时候学习脚本,你会发现sort命令后面跟了一堆类似-k1,2,或者-k1.2 -k3.4的东东,有些匪夷所思。今天,我们就来搞定它—-k选项!

1 准备素材

 

  1. $ cat facebook.txt
  2. google 110 5000
  3. baidu 100 5000
  4. guge 50 3000
  5. sohu 100 4500

 

 

第一个域是公司名称,第二个域是公司人数,第三个域是员工平均工资。(除了公司名称,其他的别信,都瞎写的^_^)

2 我想让这个文件按公司的字母顺序排序,也就是按第一个域进行排序:(这个facebook.txt文件有三个域)

 

  1. $ sort -t ' ' -k 1 facebook.txt
  2. baidu 100 5000
  3. google 110 5000
  4. guge 50 3000
  5. sohu 100 4500

 

看到了吧,就直接用-k 1设定就可以了。(其实此处并不严格,稍后你就会知道)

3 我想让facebook.txt按照公司人数排序

 

  1. $ sort -n -t ' ' -k 2 facebook.txt
  2. guge 50 3000
  3. baidu 100 5000
  4. sohu 100 4500
  5. google 110 5000

 

不用解释,我相信你能懂。

但是,此处出现了问题,那就是baidu和sohu的公司人数相同,都是100人,这个时候怎么办呢?按照默认规矩,是从第一个域开始进行升序排序,因此baidu排在了sohu前面。

4  我想让facebook.txt按照公司人数排序,人数相同的按照员工平均工资升序排序:

 

  1. $ sort -n -t ' ' -k 2 -k 3 facebook.txt
  2. guge 50 3000
  3. sohu 100 4500
  4. baidu 100 5000
  5. google 110 5000

 

看,我们加了一个-k2 -k3就解决了问题。对滴,sort支持这种设定,就是说设定域排序的优先级,先以第2个域进行排序,如果相同,再以第3个域进行排序。(如果你愿意,可以一直这么写下去,设定很多个排序优先级)

5 我想让facebook.txt按照员工工资降序排序,如果员工人数相同的,则按照公司人数升序排序:(这个有点难度喽)

 

  1. $ sort -n -t ' ' -k 3r -k 2 facebook.txt
  2. baidu 100 5000
  3. google 110 5000
  4. sohu 100 4500
  5. guge 50 3000

 

此处有使用了一些小技巧,你仔细看看,在-k 3后面偷偷加上了一个小写字母r。你想想,再结合我们上一篇文章,能得到答案么?揭晓:r和-r选项的作用是一样的,就是表示逆序。因为sort默认是按照升序排序的,所以此处需要加上r表示第三个域(员工平均工资)是按照降序排序。此处你还可以加上n,就表示对这个域进行排序时,要按照数值大小进行排序,举个例子吧:

 

  1. $ sort -t ' ' -k 3nr -k 2n facebook.txt
  2. baidu 100 5000
  3. google 110 5000
  4. sohu 100 4500
  5. guge 50 3000

 

看,我们去掉了最前面的-n选项,而是将它加入到了每一个-k选项中了。

6 -k选项的具体语法格式

要继续往下深入的话,就不得不来点理论知识。你需要了解-k选项的语法格式,如下:

[ FStart [ .CStart ] ] [ Modifier ] [ , [ FEnd [ .CEnd ] ][ Modifier ] ]

这个语法格式可以被其中的逗号(“,”)分为两大部分,Start部分和End部分。

先给你灌输一个思想,那就是“如果不设定End部分,那么就认为End被设定为行尾”。这个概念很重要的,但往往你不会重视它。

Start部分也由三部分组成,其中的Modifier部分就是我们之前说过的类似n和r的选项部分。我们重点说说Start部分的FStart和C.Start。

C.Start也是可以省略的,省略的话就表示从本域的开头部分开始。之前例子中的-k 2和-k 3就是省略了C.Start的例子喽。

FStart.CStart,其中FStart就是表示使用的域,而CStart则表示在FStart域中从第几个字符开始算“排序首字符”。

同理,在End部分中,你可以设定FEnd.CEnd,如果你省略.CEnd,则表示结尾到“域尾”,即本域的最后一个字符。或者,如果你将CEnd设定为0(零),也是表示结尾到“域尾”。

7 突发奇想,从公司英文名称的第二个字母开始进行排序:

 

  1. $ sort -t ' ' -k 1.2 facebook.txt
  2. baidu 100 5000
  3. sohu 100 4500
  4. google 110 5000
  5. guge 50 3000

 

看,我们使用了-k 1.2,这就表示对第一个域的第二个字符开始到本域的最后一个字符为止的字符串进行排序。你会发现baidu因为第二个字母是a而名列榜首。sohu和google第二个字符都是o,但sohu的h在google的o前面,所以两者分别排在第二和第三。guge只能屈居第四了。

8 又突发奇想,,只针对公司英文名称的第二个字母进行排序,如果相同的按照员工工资进行降序排序:

 

  1. $ sort -t ' ' -k 1.2,1.2 -k 3,3nr facebook.txt
  2. baidu 100 5000
  3. google 110 5000
  4. sohu 100 4500
  5. guge 50 3000

 

由于只对第二个字母进行排序,所以我们使用了-k 1.2,1.2的表示方式,表示我们“只”对第二个字母进行排序。(如果你问“我使用-k 1.2怎么不行?”,当然不行,因为你省略了End部分,这就意味着你将对从第二个字母起到本域最后一个字符为止的字符串进行排序)。对于员工工资进行排序,我们也使用了-k 3,3,这是最准确的表述,表示我们“只”对本域进行排序,因为如果你省略了后面的3,就变成了我们“对第3个域开始到最后一个域位置的内容进行排序”了。

9 在modifier部分还可以用到哪些选项?

可以用到b、d、f、i、n 或 r。

其中n和r你肯定已经很熟悉了。

b表示忽略本域的签到空白符号。

d表示对本域按照字典顺序排序(即,只考虑空白和字母)。

f表示对本域忽略大小写进行排序。

i表示忽略“不可打印字符”,只针对可打印字符进行排序。(有些ASCII就是不可打印字符,比如\a是报警,\b是退格,\n是换行,\r是回车等等)

10 思考思考关于-k和-u联合使用的例子:

 

  1. $ cat facebook.txt
  2. google 110 5000
  3. baidu 100 5000
  4. guge 50 3000
  5. sohu 100 4500

 

这是最原始的facebook.txt文件。

 

  1. $ sort -n -k 2 facebook.txt
  2. guge 50 3000
  3. baidu 100 5000
  4. sohu 100 4500
  5. google 110 5000
  6. $ sort -n -k 2 -u facebook.txt
  7. guge 50 3000
  8. baidu 100 5000
  9. google 110 5000

 

当设定以公司员工域进行数值排序,然后加-u后,sohu一行就被删除了!原来-u只识别用-k设定的域,发现相同,就将后续相同的行都删除。

 

  1. $ sort -k 1 -u facebook.txt
  2. baidu 100 5000
  3. google 110 5000
  4. guge 50 3000
  5. sohu 100 4500
  6. $ sort -k 1.1,1.1 -u facebook.txt
  7. baidu 100 5000
  8. google 110 5000
  9. sohu 100 4500

 

这个例子也同理,开头字符是g的guge就没有幸免于难。

 

  1. $ sort -n -k 2 -k 3 -u facebook.txt
  2. guge 50 3000
  3. sohu 100 4500
  4. baidu 100 5000
  5. google 110 5000

 

咦!这里设置了两层排序优先级的情况下,使用-u就没有删除任何行。原来-u是会权衡所有-k选项,将都相同的才会删除,只要其中有一级不同都不会轻易删除的:)(不信,你可以自己加一行sina 100 4500试试看)

11 最诡异的排序:

 

  1. $ sort -n -k 2.2,3.1 facebook.txt
  2. guge 50 3000
  3. baidu 100 5000
  4. sohu 100 4500
  5. google 110 5000

 

以第二个域的第二个字符开始到第三个域的第一个字符结束的部分进行排序。

第一行,会提取0 3,第二行提取00 5,第三行提取00 4,第四行提取10 5。

又因为sort认为0小于00小于000小于0000….

因此0 3肯定是在第一个。10 5肯定是在最后一个。但为什么00 5却在00 4前面呢?(你可以自己做实验思考一下。)

答案揭晓:原来“跨域的设定是个假象”,sort只会比较第二个域的第二个字符到第二个域的最后一个字符的部分,而不会把第三个域的开头字符纳入比较范围。当发现00和00相同时,sort就会自动比较第一个域去了。当然baidu在sohu前面了。用一个范例即可证实:

 

  1. $ sort -n -k 2.2,3.1 -k 1,1r facebook.txt
  2. guge 50 3000
  3. sohu 100 4500
  4. baidu 100 5000
  5. google 110 5000

 

12 有时候在sort命令后会看到+1 -2这些符号,这是什么东东?

关于这种语法,最新的sort是这么进行解释的:

On older systems, 'sort' supports an obsolete origin-zero syntax '+POS1 [-POS2]' for specifying sort keys.  POSIX 1003.1-2001 (*note Standards conformance::) does not allow this; use '-k' instead.

原来,这种古老的表示方式已经被淘汰了,以后可以理直气壮的鄙视使用这种表示方法的脚本喽!

(为了防止古老脚本的存在,在这再说一下这种表示方法,加号表示Start部分,减号表示End部分。最最重要的一点是,这种方式方法是从0开始计数的,以前所说的第一个域,在此被表示为第0个域。以前的第2个字符,在此表示为第1个字符。明白?)

结束语:

本文是互联网上仅有的比较全的关于sort的k选项的论述文章,如需转载请务必注明“转自Linux大棚-Linux主题博客”,谢谢各位:)

sort的-k选项基本就是这堆内容了,如果大家有什么补充,就留言吧:) 欢迎交流!

 
posted on 2015-11-13 15:32  xxxxxxxx1x2xxxxxxx  阅读(364)  评论(0编辑  收藏  举报