Сортировка по столбцу не работает должным образом.

Вопрос или проблема

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.

https://docs.raku.org/routine/sort
https://raku.org

Ответ или решение

Когда возникает проблема с сортировкой данных по колонкам, важно учитывать специфику используемых инструментов, таких как awk и sort. Давайте разберем вашу ситуацию более подробно, чтобы понять, какие ошибки были допущены и как их избежать.

Проблема

Ваша команда sort -t" " -nk4 marks.txt возвращает оригинальный файл без изменений. Это происходит из-за того, что sort будет считать каждое пробел как разделитель полей, а не блок из последовательных пробелов. В результате, данные не обрабатываются так, как вы ожидали.

Разъяснение

  1. Способ обработки разделителей:

    • Команда awk -F" " использует один пробел как разделитель, но по умолчанию, awk также обрабатывает последовательные пробелы как один разделитель. Это означает, что если в вашей строке есть несколько пробелов между полями, все они будут игнорироваться, и строка будет разбита на правильные колонки.
    • Напротив, sort -t" " рассматривает каждый пробел как отдельный разделитель, что приводит к неправильному разбиению строк на поля.
  2. Как правильно использовать сортировку:
    Чтобы правильно отсортировать данные, вам необходимо использовать тот же подход, что и в awk, при сортировке:

    sort -k4 -n marks.txt

    Этот вариант sort позволяет вам указать, что сорти́ровка должна выполняться по четвертому полю (-k4), а флаг -n указывает, что следует производить числовую сортировку.

Рекомендации по решению проблемы

  1. Использование awk для предварительной обработки:
    Вместо использования sort с пробелами как разделителями, вы можете использовать awk для добавления табуляции перед выполнением сортировки:

    awk '{ print $NF"\t"$0 }' marks.txt | sort -n | cut -f2-
  2. Оптимизация работы с полями:
    Убедитесь, что вы правильно обрабатываете итоговые данные. Например, если вы хотите работать с последним полем, вы можете использовать:

    awk -v OFS='\t' '{ print $NF, $0 }' marks.txt | sort -n | cut -f2-
  3. Сравнение подходов:
    Убедитесь, что ваше использование awk и sort соответствует базе данных. Например, использование -F в awk или -t в sort должно быть согласовано, чтобы избежать путаницы.

Заключение

Правильная сортировка строк в текстовом файле требует учета способа обработки разделителей. Различие в поведении awk и sort может привести к неожиданным результатам, если не принять это во внимание. Используя предложенные выше команды, вы сможете добиться нужного результата, а также оптимизировать свои скрипты для будущей работы с подобными данными.

Для более детальной информации стоит ознакомиться с документацией соответствующих команд или задать вопросы на специализированных форумах, таких как Stack Overflow, где сообщества готовы помочь разобраться с более сложными случаями.

Оцените материал
Добавить комментарий

Капча загружается...