【问题标题】:Unix sort string and number togetherUnix将字符串和数字排序在一起
【发布时间】:2023-03-23 10:47:01
【问题描述】:

我有一个我认为应该是常见问题的问题,但我还没有找到任何好的解决方案。

我有一个文件,其中每一行都有一个染色体编号、染色体中的起始位置和一些相关值,如下所示。

1       1.07299851019   1       1.07299851019   HQ      chrY    2845223         +       0.251366120219  46      
1       1.06860686763   1       1.06860686763   HQ      chr10   88595309        +       0.256830601093  47      
1       1.04688316093   3       3.14064948278   HQ      chr6    49126474        +       0.295081967213  54      
1       1.1563829915    1       1.1563829915    HQ      chrX    16428176        +       0.185792349727  34      

我想在染色体(第 6 列)和起始位置(第 7 列)上使用 unix 排序命令对这个文件进行排序。在四处搜索后,我想出了这个,这让我非常接近:

nohup sort -t $'\t' -k 6.4,6.5n -k 7,7n   

我无法解决的剩下的问题是,虽然用数字编号的染色体可以正常排序,但 X 和 Y 染色体在起始位置上被排序在一起,如下所示:

1       0.978579587641  9       8.80721628876   HQ      chrX    2861057 -       0.431693989071  79      
1       0.979500536702  1       0.979500536702  HQ      chrY    2861314 -       0.420765027322  77      
1       0.969979601694  9       8.72981641525   HQ      chrX    2861649 -       0.469945355191  86   

我知道有可能解决例如通过用数字替换 chrX 和 chrY,或者编写一个程序来解决它,但是能够使用一个简单的命令会非常好,特别是因为文件大小通常很大而且我反复这样做。

如果染色体按照 1 到 22 的顺序排列,然后是 X 和 Y。我的命令先是 X 和 Y,然后是 1 到 22 号染色体。

【问题讨论】:

    标签: string unix sorting numbers


    【解决方案1】:

    要将XY 分开,您可以指定一个备用键:

    nohup sort -t $'\t' -k 6.4,6.5n -k 6 -k 7,7n
    

    (这表示如果字段6.4,6.5 中的两行在数值上是相等的,那么下一步是在字段6 中比较它们-在尝试字段之前7)。

    免责声明:这不满足您最后一段中的目标:

    如果染色体按照 1 到 22 的顺序排列,然后是 X 和 Y。我的命令先是 X 和 Y,然后是 1 到 22 号染色体。

    因为XY 在数字排序期间仍将被视为零,并且回退不会改变这一点。无论如何,希望你觉得它很有用。

    我知道有可能解决例如通过用数字替换 chrX 和 chrY,[…]

    确实,您可以即时进行替换:

    sed 's/chrX/chr23/; s/chrY/chr24/' |
      sort -t $'\t' -k 6.4,6.5n -k 7,7n |
      sed 's/chr23/chrX/; s/chr24/chrY/'
    

    (请注意,此命令中的换行符是可选的;我将它们包括在内是为了便于阅读,但如果您愿意,如果/当您实际使用它时,您可以将其放在一行中。)

    【讨论】:

    • 非常感谢 ruakh,sed 命令完全符合我的要求!
    【解决方案2】:

    如果您的sort 版本支持用于对字母数字列进行排序的-V 选项,那么您可以执行以下操作:

    $ cat file
    1   1.07299851019   1   1.07299851019   HQ  chrY    2845223     +   0.251366120219  46
    1   1.06860686763   1   1.06860686763   HQ  chr10   88595309    +   0.256830601093  47
    1   1.04688316093   3   3.14064948278   HQ  chr6    49126474    +   0.295081967213  54
    1   1.1563829915    1   1.1563829915    HQ  chrX    16428176    +   0.185792349727  34
    

    $ sort -t$'\t' -k6V -k7n file
    1   1.04688316093   3   3.14064948278   HQ  chr6    49126474    +   0.295081967213  54
    1   1.06860686763   1   1.06860686763   HQ  chr10   88595309    +   0.256830601093  47
    1   1.1563829915    1   1.1563829915    HQ  chrX    16428176    +   0.185792349727  34
    1   1.07299851019   1   1.07299851019   HQ  chrY    2845223     +   0.251366120219  46
    

    【讨论】:

    • 谢谢JS,这似乎是我想要的。不幸的是,我的版本不支持 -V 选项。
    【解决方案3】:

    详细说明 jaypal 之前的回答...

    您可以像这样更改每列的排序标准:

    sort -k1,1V input.txt

    这将使用上述 -V 选项对第 1 列且仅第 1 列进行排序,该选项如下引用自 here

    -V 的意思是“文本中自然排序的(版本)数字”(类型 man sort to find),它神奇地对数字和文本进行排序。

    如果您在制表符分隔的文件中有多个列,并且您想要指定主要列的排序顺序,您可以执行以下操作:

    sort -k14,14V -k1,1n input.txt

    上面将使用第14列作为第一个排序索引并应用-V排序算法,然后将使用第1列作为二级排序索引并使用数字排序。 (这在某些圈子中可能对按染色体排序然后位置有用)。

    解决 OSX 用户缺少的 -V 选项:

    Mac OS X 原生排序不支持 -V,您将拥有 安装 GNU 核心实用程序并改用 gsort。

    要快速了解-V 排序的工作原理,您可以查看以下示例...

    示例输入:

    chr21   
    chr2    
    chr3    
    chrY    
    chr1    
    chr3    
    chr10   
    chrX    
    

    V 排序输出:

    chr1    
    chr2    
    chr3    
    chr3    
    chr10   
    chr21   
    chrX    
    chrY    
    

    【讨论】:

      猜你喜欢
      • 2019-01-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多