【问题标题】:how to sort alphanumerically in Unix with sort? More complex than seems如何在 Unix 中使用 sort 对字母数字进行排序?比看起来更复杂
【发布时间】:2012-01-13 18:55:22
【问题描述】:

我正在尝试使用 unix sort 命令以“直观”/自然的方式对一串字母和数字进行字母数字排序,但无法正确排序。我有这个文件:

$ cat ~/headers 
@42EBKAAXX090828:6:100:1699:328/2
@42EBKAAXX090828:6:10:1077:1883/2
@42EBKAAXX090828:6:102:785:808/2

我想按字母数字对其进行排序,直观上 @42EBKAAXX090828:6:10:... 排在第一位(因为 10 小于 100102),第二位是 @42EBKAAXX090828:6:100...,第三位是 @42EBKAAXX090828:6:102:204:1871/2

我知道建议对行内的特定位置进行排序,但这里 : 的位置可能会有所不同,因此这不是一个通用且可行的解决方案。

我试过了:

sort --stable -k1,1 ~/headers > foo

-n-u 参数的各种组合,但它没有给出正确的顺序。

如何通过使用sort 的bash 或Python 有效地完成这项工作?我想将此应用于大小约为 4-5 GB 的文件,因此包含数百万行。

谢谢!

【问题讨论】:

  • 仅供参考,这通常称为“自然排序”。
  • 不确定性能,但这里是python中自然排序的实现:stackoverflow.com/q/4836710/331473
  • 您将如何处理@42EBKAAXX09082*7*:6:100:1699:328/2@42EBKAAXX09082*8*:6:100:1699:328/2(强调*s)?它们的排序相同吗? (即只有第三个字段是相关的)然后@JonathanM 的答案是最好的。否则看看我的

标签: python bash shell unix sorting


【解决方案1】:

-V 选项似乎可以满足您的需求 - 自然排序。显然用于版本号(因此选择了字母)

sort -V ~/headers

输出

@42EBKAAXX090828:6:10:1077:1883/2
@42EBKAAXX090828:6:100:1699:328/2
@42EBKAAXX090828:6:102:785:808/2

【讨论】:

  • 哪个 ofc 未记录 ~~~~~
  • @user528025 不,它已记录在案,我通过在手册页中搜索“自然排序”找到了此选项。
【解决方案2】:

按字母顺序对它进行排序,就像在您的示例中一样。 10: 出现在 100102 之后的原因是 10: 在它们之后,因为冒号 :9 字符之后 ASCII chart

如果您想对以冒号分隔的第三个字段进行排序,请尝试以下操作:

sort -t':' -k3 ~/headers > foo

【讨论】:

  • 如果 OP 只想在该字段上排序,这是一个很好的答案
  • 使用-k3n-k3,4n 可能更好,这样910 之前排序。有空间认为 OP 可能希望 '@43ZQRY101112:6:19:221:134/3' 在显示的行之后排序,而不是排在第二位,因此排序可能需要在更多键上而不是第三个键上。想知道数据“@6NBGD010101:9:99:999:111/3”或“@213QED081231:16:91:23:2/0”是否会出现,以及这些数据相对于行应该出现在哪里开始'@42E'。到目前为止,问题还没有得到充分说明,因为我们没有全面了解传入数据的可变性。
  • @JonathanLeffler,很有可能。好评论。谢谢。
  • @JonathanLeffler:感谢您指出这一点。需要明确的是,顺序是将“:”视为数量级,从高到低,以十进制数表示。所以“6:500”在“7:10”之前,“2:200”在“6:500”之前。这就是为什么我认为对特定冒号字段编号进行排序的解决方案不起作用的原因。有替代方案吗?谢谢。
  • @user248237:你关心第一个冒号之前字段的相对顺序吗?它们是最重要还是最不重要的排序字段?第一个字段是否可以使用“直接代码集顺序”排序?如果您只需要按数字顺序排序的第一个冒号到斜杠之后的 4 个字段,那么 sort -t: -k2,3n -k3,4n -k4,5n -k5,6n 应该可以解决问题。如果您需要对第一个字段进行特殊处理,那么它会变得更加复杂。
【解决方案3】:

这通常称为自然排序。这是适用于您的示例数据集的一种方法。

import re

def natural_sorted(iterable, reverse=False):
    """Return a list sorted the way that humans expect."""
    def convert(text):
        return int(text) if text.isdigit() else text
    def natural(item):
        return map(convert, re.split('([0-9]+)', item))
    return sorted(iterable, key=natural, reverse=reverse)

我找到了这个here 并有所改进。

【讨论】:

  • 这会相对于 Unix 排序进行扩展吗?它可以处理数百万行长的文件吗?
猜你喜欢
  • 2023-04-04
  • 1970-01-01
  • 1970-01-01
  • 2015-01-20
  • 2011-01-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多