Вопрос или проблема
cat marks.txt
возвращает
1) Amit Physics 80
2) Rahul Maths 90
3) Shyam Biology 87
4) Kedar English 85
5) Hari History 89
awk -F" " '{ print $4"\t" $0 }' marks.txt | sort | cut -f 2-
успешно отсортировал текст по четвертому столбцу.
контекст: https://stackoverflow.com/questions/17048188/how-to-use-awk-sort-by-column-3
но чтобы эмулировать самый голосуемый ответ: sort -t" " -nk4 marks.txt
но возвращает только:
1) Amit Physics 80
2) Rahul Maths 90
3) Shyam Biology 87
4) Kedar English 85
5) Hari History 89
почему клаузула сортировки не работает?
использование sort -t' '
(символ пробела как разделитель полей здесь) будет считать каждое отдельное пространство как разделитель поля, а не все последовательные пробелы как один разделитель, что является причиной, почему это не дает ожидаемого результата, и поэтому было предложено первое решение команды, которое отделяет последнее поле с помощью выделенного табулятора, а затем сортирует на основе этого поля и потом удаляет это из вывода.
Обратите внимание, что использование -F" "
здесь в команде awk не имеет побочного эффекта на вывод команды или обработку, и его можно также удалить; дополнительно, зная, что в awk использование -F" "
будет считать любые последовательные пробелы как один разделитель, в то время как в sort -t" "
будет считать каждое отдельное пространство как отдельный разделитель (эквивалент в awk — это -F"[ ]"
, т. е. определение разделителя полей как регулярного выражения).
В конечном итоге, вам будет лучше сделать так:
awk '{ print $NF"\t"$0 }' marks.txt |sort |cut -f2-
Разница между использованием -F
с пробелом в awk
и использованием -t
с пробелом в sort
следующая:
-
awk -F ' '
то же самое, что и простоawk
. Один пробел является значением по умолчанию дляFS
(внутренний разделитель полей) и приведет к тому, чтоawk
обрежет фланкирующие пробелы (табуляции и/или пробелы) из данных, а также будет рассматривать подстроки, разделенные пробелами, как поля. -
sort -t ' '
будет считать каждое отдельное пространство как разделитель. Использованиеsort
без-t
заставит утилиту разделять каждую строку на поля так же, как делает этоawk
, по группам последовательных пробелов (табуляций и/или пробелов).
Ваша первая команда,
awk -F" " '{ print $4"\t" $0 }' marks.txt | sort -n | cut -f 2-
(Шварца) по сути та же самая, что и
awk '{ print $4 "\t" $0 }' marks.txt | sort -n | cut -f 2-
или, используя OFS
для установки разделителя выходных полей на табуляцию,
awk -v OFS='\t' '{ print $4, $0 }' marks.txt | sort -n | cut -f 2-
(Обратите внимание также на добавление -n
к sort
выше; мы хотим сортировать численно.)
Явный доступ к последнему полю каждой строки позволяет другим полям иметь переменное количество (если, например, они содержат пробелы):
awk -v OFS='\t' '{ print $NF, $0 }' marks.txt | sort -n | cut -f 2-
Ваша sort
команда может быть переписана для корректной числовой сортировки по 4-му столбцу, разделенному пробелами, так:
sort -k 4n marks.txt
Это, очевидно, предполагает, что каждая строка данных всегда будет содержать ровно четыре поля, разделенных пробелами.
Используя Raku (ранее известный как Perl_6)
~$ raku -e '.say for lines() \
.map( *.split: /\h+/) \
.sort( +*.[3] ) \
.map( *.join: "\t" );' file.txt
Пример входных данных:
1) Amit Physics 80
2) Rahul Maths 90
3) Shyam Biology 87
4) Kedar English 85
5) Hari History 89
Пример выходных данных:
1) Amit Physics 80
4) Kedar English 85
3) Shyam Biology 87
5) Hari History 89
2) Rahul Maths 90
Сортировка: Добавление знака +
(числовая принудительная конвертация) в приведенном выше коде на самом деле избыточно, но включено, чтобы предложить, что для получения обратной числовой сортировки вам нужно использовать .sort( -*.[3] )
.
Расстояние между столбцами: Вы можете join
на "\t\t"
для лучшего расстояния между столбцами, и/или направить в | column -t
.
Ответ или решение
Когда возникает проблема с сортировкой данных по колонкам, важно учитывать специфику используемых инструментов, таких как awk
и sort
. Давайте разберем вашу ситуацию более подробно, чтобы понять, какие ошибки были допущены и как их избежать.
Проблема
Ваша команда sort -t" " -nk4 marks.txt
возвращает оригинальный файл без изменений. Это происходит из-за того, что sort
будет считать каждое пробел как разделитель полей, а не блок из последовательных пробелов. В результате, данные не обрабатываются так, как вы ожидали.
Разъяснение
-
Способ обработки разделителей:
- Команда
awk -F" "
использует один пробел как разделитель, но по умолчанию,awk
также обрабатывает последовательные пробелы как один разделитель. Это означает, что если в вашей строке есть несколько пробелов между полями, все они будут игнорироваться, и строка будет разбита на правильные колонки. - Напротив,
sort -t" "
рассматривает каждый пробел как отдельный разделитель, что приводит к неправильному разбиению строк на поля.
- Команда
-
Как правильно использовать сортировку:
Чтобы правильно отсортировать данные, вам необходимо использовать тот же подход, что и вawk
, при сортировке:sort -k4 -n marks.txt
Этот вариант
sort
позволяет вам указать, что сорти́ровка должна выполняться по четвертому полю (-k4
), а флаг-n
указывает, что следует производить числовую сортировку.
Рекомендации по решению проблемы
-
Использование
awk
для предварительной обработки:
Вместо использованияsort
с пробелами как разделителями, вы можете использоватьawk
для добавления табуляции перед выполнением сортировки:awk '{ print $NF"\t"$0 }' marks.txt | sort -n | cut -f2-
-
Оптимизация работы с полями:
Убедитесь, что вы правильно обрабатываете итоговые данные. Например, если вы хотите работать с последним полем, вы можете использовать:awk -v OFS='\t' '{ print $NF, $0 }' marks.txt | sort -n | cut -f2-
-
Сравнение подходов:
Убедитесь, что ваше использованиеawk
иsort
соответствует базе данных. Например, использование-F
вawk
или-t
вsort
должно быть согласовано, чтобы избежать путаницы.
Заключение
Правильная сортировка строк в текстовом файле требует учета способа обработки разделителей. Различие в поведении awk
и sort
может привести к неожиданным результатам, если не принять это во внимание. Используя предложенные выше команды, вы сможете добиться нужного результата, а также оптимизировать свои скрипты для будущей работы с подобными данными.
Для более детальной информации стоит ознакомиться с документацией соответствующих команд или задать вопросы на специализированных форумах, таких как Stack Overflow, где сообщества готовы помочь разобраться с более сложными случаями.