как отсортировать алфавитно-цифровую в Unix с сортировкой? Сложнее, чем кажется - PullRequest
4 голосов
/ 06 декабря 2011

Я пытаюсь отсортировать строку букв и цифр буквенно-цифровым способом "интуитивно" / естественным путем с помощью команды 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 ГБ, содержащим миллионы строк.

Спасибо!

Ответы [ 3 ]

11 голосов
/ 06 декабря 2011

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

sort -V ~/headers

выходы

@42EBKAAXX090828:6:10:1077:1883/2
@42EBKAAXX090828:6:100:1699:328/2
@42EBKAAXX090828:6:102:785:808/2
4 голосов
/ 06 декабря 2011

Это - это сортировка по алфавиту, как в вашем примере.Причина 10: наступает после 100 и 102 в том, что 10: - это после них, поскольку двоеточие : находится после символа 9 на диаграмме ASCII.

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

sort -t':' -k3 ~/headers > foo
0 голосов
/ 06 декабря 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)

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...