как сортировать по алфавиту в Unix с сортировкой? Более сложный, чем кажется

Я пытаюсь отсортировать строку букв и цифр в алфавитно-цифровом порядке «интуитивным»/естественным способом с помощью команды 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 меньше, чем 100 и 102), вторым является @42EBKAAXX090828:6:100..., а третьим - @42EBKAAXX090828:6:102:204:1871/2.

Я знаю, что предлагается сортировать по определенной позиции в строке, но положение : здесь может варьироваться, и поэтому это не будет общим и работоспособным решением.

Я старался:

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

с различными комбинациями параметров -n и -u, но это не дает правильного порядка.

Как это можно сделать эффективно, либо из bash, используя sort, либо из Python? Я хотел бы применить это к файлам размером около 4-5 ГБ, содержащим миллионы строк.

Спасибо!


person Community    schedule 06.12.2011    source источник
comment
К вашему сведению, это обычно называется естественной сортировкой.   -  person yak    schedule 06.12.2011
comment
Не уверен насчет производительности, но вот реализация естественной сортировки в python: stackoverflow.com/q/4836710/331473   -  person Adam Wagner    schedule 06.12.2011
comment
как бы вы справились с @42EBKAAXX09082*7*:6:100:1699:328/2 и @42EBKAAXX09082*8*:6:100:1699:328/2 (*s для акцента)? они сортируются одинаково? (т.е. имеет значение только 3-е поле), тогда ответ @JonathanM лучше всего. В противном случае взгляните на мой   -  person tobyodavies    schedule 06.12.2011


Ответы (3)


опция -V делает то, что вы хотите - естественную сортировку. Очевидно, предназначен для номеров версий (отсюда и выбрана буква)

sort -V ~/headers

выходы

@42EBKAAXX090828:6:10:1077:1883/2
@42EBKAAXX090828:6:100:1699:328/2
@42EBKAAXX090828:6:102:785:808/2
person tobyodavies    schedule 06.12.2011
comment
какой из них НЕДОКУМЕНТИРОВАН ~~~~~ - person user528025; 07.06.2013
comment
@ user528025 нет, это задокументировано, я нашел эту опцию, выполнив поиск на странице руководства для естественной сортировки. - person tobyodavies; 11.06.2013

Он сортирует его по алфавиту, как в вашем примере. Причина, по которой 10: идет после 100 и 102, заключается в том, что 10: стоит после них, так как двоеточие : стоит после символа 9 в диаграмма ASCII.

Если вы хотите выполнить сортировку по третьему полю, разделенному двоеточием, попробуйте следующее:

sort -t':' -k3 ~/headers > foo
person Jonathan M    schedule 06.12.2011
comment
Хороший ответ, если OP хочет сортировать только по этому полю. - person tobyodavies; 06.12.2011
comment
Вероятно, лучше использовать -k3n или -k3,4n, чтобы 9 сортировалось до 10. Есть место подумать, что OP может захотеть, чтобы «@43ZQRY101112:6:19:221:134/3» сортировалось после показанных строк, а не на втором месте, поэтому сортировка, вероятно, должна быть по большему количеству ключей, чем только по третьему. Было бы интересно узнать, могут ли появляться данные «@6NBGD010101:9:99:999:111/3» или «@213QED081231:16:91:23:2/0» и где они должны появляться относительно строк начиная с '@42E'. Проблема пока недостаточно конкретизирована, потому что у нас нет полной картины изменчивости поступающих данных. - person Jonathan Leffler; 06.12.2011
comment
@JonathanLeffler, вполне возможно. Хороший комментарий. Спасибо. - person Jonathan M; 06.12.2011
comment
@JonathanLeffler: спасибо, что указали на это. Чтобы было ясно, порядок заключается в том, чтобы рассматривать ':', как если бы они были порядками величины, от большего к меньшему, в десятичных числах. Таким образом, 6:500 предшествует 7:10, а 2:200 предшествует 6:500. Вот почему я не думаю, что решение сортировки по количеству полей с двоеточием будет работать. Есть ли альтернатива этому? Спасибо. - person ; 06.12.2011
comment
самый верный ответ на это заключается в том, что я хотел бы быть идентичен тому, как сортирует программа samtools с опцией samtools sort -n, но, к сожалению, я нигде не могу найти точное описание того, какую процедуру сортировки она использует... кто-нибудь знает? ? - person ; 06.12.2011
comment
@ user248237: Вас волнует относительный порядок полей перед первым двоеточием? Являются ли они наиболее или наименее важными для сортировки? И подходит ли сортировка «прямой кодовый набор» для первого поля? Если вам нужны только 4 поля после первого двоеточия до косой черты, отсортированные в числовом порядке, то sort -t: -k2,3n -k3,4n -k4,5n -k5,6n должен помочь. Если вам нужно специально обработать первое поле, оно становится более сложным. - person Jonathan Leffler; 06.12.2011
comment
Есть прекрасная статья «Теория и практика построения рабочей процедуры сортировки» Дж. П. Линдермана. В конце он показывает, что лучший (или, по крайней мере, хороший) способ улучшить производительность сортировки сложных ключей — это написать код преобразования, который помещает ключи в начале каждой строки в легко сортируемом формате, а затем передает данные в основную сортировку, а затем убирает ключ сортировки с выходных строк. Это уменьшает накладные расходы на интерпретацию каждой строки, что ускоряет сортировку. К сожалению, статью трудно найти в Интернете; Google находит ссылки, но не статью. - person Jonathan Leffler; 06.12.2011
comment
@user248237 user248237, если вы хотите, чтобы : действовал как разделитель порядка величины, посмотрите мой ответ. - person tobyodavies; 06.12.2011

Обычно это называется естественной сортировкой. Вот один из способов, который работает для вашего примера набора данных.

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)

Я нашел это здесь и немного улучшилось.

person yak    schedule 06.12.2011
comment
будет ли это масштабироваться по сравнению с сортировкой Unix? Может ли он работать с файлами длиной в миллионы строк? - person ; 06.12.2011