Вопрос или проблема
Предположим, у меня есть следующий файл.txt:
foo-a baz
foo bar
foo-c baz
Если я выполню sort file.txt
, я получу такой же вывод:
foo-a baz
foo bar
foo-c baz
Поскольку
(пробел) идет перед -
в ASCII, я ожидал увидеть следующий вывод:
foo bar
foo-a baz
foo-c baz
Даже если sort
рассматривает целые слова, я все равно ожидал, что foo
будет перед foo-a
и foo-c
.
Я пробовал sort -d
(словарный), sort -g
(общий числовой) и sort -h
(человеческий числовой) без успеха. Есть ли способ получить нужный мне порядок с помощью sort? В противном случае с использованием другого базового инструмента (я понимаю, что это было бы легко сделать на python, perl, ruby и т.д., но я пишу оболочку, которая должна быть переносимой).
В локали C
сортировка предполагает основание на порядке символов в ASCII, даже на (редких) системах, которые не основаны на ASCII.
На практике 99,99% систем основаны на ASCII, и реализации sort
в этой локали просто сортируют по байтовому значению, не заботясь о том, какие символы эти байты представляют.
Аспект сортировки локализации контролируется переменной окружения LC_COLLATE
, хотя будьте осторожны, что LC_ALL
, если установлено, имеет приоритет над всеми остальными переменными LC_*
.
LC_CTYPE
также контролирует, как байты декодируются в символы на входе (и символы кодируются обратно в байты на выходе), установка его на C
также помогает избежать возможной двусмысленности, если в входных данных есть не-ASCII символы, и делает декодирование/кодирование быстрее (просто пропуск, как упоминалось выше).
И как только вы установите LC_CTYPE
на C
, вы можете также установить LC_MESSAGES
и все остальные, так как, вероятно, сообщения об ошибках на языке пользователя в любом случае не могут быть отображены в ASCII.
Так что в целом, установка LC_ALL
на C
решает все проблемы:
$ LC_ALL=C sort file.txt
foo bar
foo-a baz
foo-c baz
Больше об этом по адресу: Что делает “LC_ALL=C”?
Ответ или решение
Чтобы отсортировать строки текста в файле в порядке ASCII, вы можете использовать утилиту sort
в Unix-подобных операционных системах. Однако, как показано в вашем примере, поведение sort
может зависеть от настройки локали системы. Давайте рассмотрим, как можно достичь желаемого результата сортировки с учетом специфики ASCII.
Шаги для сортировки строк по порядку ASCII
-
Создание файла: Убедитесь, что у вас есть текстовый файл, содержащий строки, которые вы хотите отсортировать. Например, создайте файл
file.txt
с содержимым:foo-a baz foo bar foo-c baz
-
Проверка локали: По умолчанию
sort
может использовать локаль, отличную от C, что может привести к неожиданным результатам сортировки. Ваша задача — использовать локальC
, которая гарантирует, что символы сортируются в соответствии с их числовыми значениями в ASCII. -
Установка локали: Перед выполнением команды сортировки установите переменную окружения
LC_ALL
вC
. Это можно сделать прямо в командной строке:LC_ALL=C sort file.txt
Эта команда означает, что
sort
будет работать в стандартной локали, где порядок символов строго соответствует их значениям в таблице ASCII. -
Ожидаемый результат: После выполнения вышеуказанной команды вы должны получить следующий вывод:
foo bar foo-a baz foo-c baz
Дополнительные параметры и их использование
-
LC_COLLATE
: Эта переменная окружения определяет правила сортировки. УстановивLC_COLLATE=C
, вы обеспечите сортировку в соответствии с ASCII. Однако использованиеLC_ALL=C
более эффективно, так как оно переопределяет все переменные локали, касающиеся каталога. -
LC_CTYPE
: Эта переменная управляет кодировкой символов. На большинстве систем использованиеC
также помогает избежать проблем с не-ASCII символами, так как это позволит избежать любой неопределенности при трактовке байтов.
Завершение
Использование команды sort
в сочетании с правильной установкой локали позволит вам достичь ожидаемого порядка строк в текстовом файле. Это решение является универсальным и совместимо с различными Unix-подобными системами, что делает его отличным выбором для написания переносимых скриптов.
Если же вы хотите более сложную сортировку или фильтрацию, вы можете рассмотреть использование языков скриптов, таких как Python или Perl, но для стандартных задач с текстом sort
с корректно заданной локалью будет вполне достаточно.
Таким образом, для сортировки строк в вашем файле по порядку ASCII, достаточно выполнить следующую команду:
LC_ALL=C sort file.txt
Этот метод является простым и эффективным способом достижения нужного результата.