再探sort命令

作者: ElephantKing | 来源:发表于2020-01-06 20:20 被阅读0次

    起因

    之前只知道sort命令可以对文本排序,用选项-t指定分隔符,用-k指定排序字段,用-n指定字段为数字。但是由于实战机会较少,真正操练起来的时候,发现捉襟见肘,可以参见下面几个情景:

    1. 以数字大小对第一个域排序(基础)
    2. 以字符顺序对第一个域排序(基础)
    3. 以字符顺序对第一个域排序,但是只考虑第3个字符到10个字符
    4. 以数字大小对第一个域排序,相同则以数字大小对第二个域排序
    5. 以数字大小对第一个域排序,相同则以字符大小对第二个域排序

    sort的规则

    1. sort的-k选项,会被局部选项和全局选项影响,局部选项覆盖全局选项,局部选项是跟在-k后面的选项,其余的为全局选项。
    2. 在不指定结束域的情况想,以数字排序,仅按指定的域排序,以字符串排序,则是指定域到行尾。
    3. 在指定域上的值相等的情况下,以字符顺序排序整行。
    4. 以数字排序时,提取域的前缀数字,处理为十进制,遇到非数字结束,所以域123abc的整数值为123。最好不要使用跨域数字排序,有个巨坑,最后再讲。
    5. 以字符串排序时,前缀相同的串,长度大的比较大。

    下面将从这几个例子来分解sort命令

    sort细节

    平时我们用的sort命令的-k选项,其实是简写的方式,其完整的命令如下:

    sort -k [FStart[.CStart]] [Modifier][, [FEnd[.CEnd]] [Modifier]] input.txt
    sort -k 3.1,3.2n input.txt

    上面的例子中的3.1,3.3n,各部分对应的值如下,其中,FStart就是要排序的起始域,CStart是起始域的第几个字符,FEnd是要排序的结束域,CEnd是结束域的第几个字符,Modifier是该排序选项的附加选项。即:对第3个域的第1到第3个字符进行数字排序。所以通常情况下的-k3则是,对第三个域到行尾进行字符顺序排序。

    FStart=3
    CStart=1
    FEnd=3
    CEnd=3
    Modifier=n
    

    例子:

    • 对第一个字段字符排序
    对第一个字段字符排序
    • 对第一个字段排序,但从第二个字符开始
    对第一个字段排序,但从第二个字符开始
    • 对第二个字符数字排序
    对第二个字符数字排序
    • 对第二个字段字符排序
    对第二个字段字符排序

    所以,以下的意思是这样的

    -k 7    #对第7列到行尾进行字符串排序
    -k 7,8  #对第7列到第8列进行字符串排序
    -k 7n    #对第7列进行数字排序
    -k 7,8n  #对第7列到第8列进行数字排序
    # 以上如果完全相等,则把 整行按字符串排序
    

    后记

    在使用时请注意几个点

    1. FStart必须小于等于EStart
    2. 如果不指定EStart,则从FStart到行尾,对字符排序和数字排序都遵守这个规则。但是数字排序就有个坑在这里:如果指定的分隔符不是逗号(,)那么跨域数字排序就没有跨域效果,栗子如下:
    # 数据文件input.txt内容如下
    a:100:400
    b:100:300
    c:10:3000
    d:20:400
    d:20:4000
    

    sort -k2,3n -t':' input.txt

    非逗号分隔符数字排序

    从上面结果可以看出,非逗号数字排序在跨域排序时,仅按起始域排序,在起始域相同的情况下,按整行字符顺序再次排序。而不是按后续域排序,从a:100:400b:100:300的排序位置可以看出。

    如果上述文件内容不变,仅把分隔符改为逗号(,),再看结果。

    image.png

    未曾改变数据,只改变了分隔符,结果大变。在这里我只能推测sort排序的数字处理方式如下:

    1. 提取指定域的内容,包括分隔符。
    2. 从左到右处理数字,同时忽略所有的逗号(可能因为有3位分数字的书写方式,1,234,567,仅猜测,我现在仅发现用逗号做分隔符的时候有这个现象),遇到非数字结束。
    3. 按上述步骤所得数字排序,如果相等则对整行字符排序。

    再来看个例子:

    奇怪的栗子

    上面这个例子可以说明,-k选项在不指定结束域时,是默认到行尾的。所以在数字排序的时候提取的是第二个域到行尾,包括分隔符(即:20,4,0,0,0),处理时忽略逗号,于是20,4,0,0,0的值实际上是204000。

    仅指定某一个域数字排序

    如果仅指定某一个域进行数字排序,请按上面这种写法。

    相关文章

      网友评论

        本文标题:再探sort命令

        本文链接:https://www.haomeiwen.com/subject/vpskactx.html