Сортировка элементов CSV-файла

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

У меня есть файл CSV с семью числами в строке, как показано ниже:

1083,20,28,42,23,10,43
1084,20,5,29,59,40,33
1085,39,50,21,12,40,55
1086,45,4,6,23,10,2
1087,36,46,28,32,3,20

Я хочу оставить первое число на месте (столбец 1) и отсортировать столбцы со 2 по 7, чтобы файл выглядел так:

1083,10,20,23,28,42,43
1084,5,20,29,33,40,59
1085,12,21,39,40,50,55
1086,2,4,6,10,45,23
1087,3,20,28,32,36,46

Как я могу сделать это с помощью awk, sed и т. д.?

Спасибо

С помощью perl:

perl -F, -lape '$_ = join ",", shift @F, sort {$a <=> $b} @F' < input.csv

С помощью GNU awk:

gawk -F, '
  {
    split($0, a)
    printf "%s", a[1]
    delete a[1]
    n = asort(a)
    for (i = 1; i <= n ; i++) printf "%s", FS a[i]
    print ""
  }' < input.csv

Или с использованием библиотеки join.awk (спасибо @WeijunZhou)

gawk -i join -F, -v OFS=, '
  {
    split($0, a)
    first = a[1]
    delete a[1]
    n = asort(a)
    print first, join(a, 1, n, OFS)
  }'

Вашей проблемой является то, что у вас файлы с концами строк MAC (\r), в то время как команды, которые вы выполняете, предполагают использование концов строк Unix (\n).

Используйте Perl:

$ perl -l015 -F, -0015 -pae '$_ = join ",", shift @F, sort { $a <=> $b } @F' input.csv

Опции:

  • -l устанавливает ORS в \r = восьмеричное 15.
  • -0 устанавливает RS в \r = восьмеричное 15.
  • -p будет перебирать ваш файл CSV построчно. Строка отделяется от входного файла с помощью RS, который установлен как \r с помощью опции -0.
  • -F устанавливает разделитель полей как запятая для каждой строки, по мере её чтения.
  • -a разбивает каждую строку по мере её чтения на поля и сохраняет их в массиве @F.
  • Примечание: порядок предоставления опций важен.

Таким образом, вывод, который вы получите, также будет иметь окончания строк MAC. Вот почему вы не видите ваш ожидаемый вывод, а все выводимые строки кажутся сжатыми в одну строку, основываясь на всех предложенных здесь решениях.

Это использует Miller (mlr), чтобы превратить текущую запись в массив, отсортировать её (исключая первый элемент), а затем переписывает отсортированные элементы обратно в запись:

$ mlr --nidx --fs comma put 'for (k,v in sort(arrayify($*)[2:-1])) { $[k+1] = v }; ' file
1083,10,20,23,28,42,43
1084,5,20,29,33,40,59
1085,12,21,39,40,50,55
1086,2,4,6,10,23,45
1087,3,20,28,32,36,46

Данные читаются и записываются как индексированный файл, разделенный запятыми. Вы также можете использовать данные как файл CSV без заголовков (в данном случае это не имеет значения):

$ mlr --csv -N put 'for (k,v in sort(arrayify($*)[2:-1])) { $[k+1] = v }; ' file
1083,10,20,23,28,42,43
1084,5,20,29,33,40,59
1085,12,21,39,40,50,55
1086,2,4,6,10,23,45
1087,3,20,28,32,36,46

Для простого csv без кавычек попробуйте следующее:

while IFS= read -r l; do
    col1=$(printf '%s' "$l" | cut -d, -f1)
    printf '%s,' "$col1"
    printf '%s' "$l" | cut -d, -f2- | grep -o "[0-9]*" | sort -n | paste -sd,
done < file

Попробовал с помощью следующего метода, сочетания awk и sed

j=awk '{print NR}' filename | sort -nr| sed -n '1p'

for ((i=1;i<=$j;i++)); do k=`awk -F "," -v  i="$i" 'NR==i {print $1}' i.txt` ;echo $k;awk -F "," -v i="$i" 'NR==i {$1=" ";print $0}' i.txt| sed -r "s/^\s+//g"| perl -pne "s/ /\n/g"| sort -n| perl -pne "s/\n/ /g";echo " "| sed "s/.*/&\n/g";done|sed '/^$/d'| sed "N;s/\n/ /g"| sed "s/ /,/g"| sed "s/\,*$//g"

вывод

1083,10,20,23,28,42,43
1084,5,20,29,33,40,59
1085,12,21,39,40,50,55
1086,2,4,6,10,23,45
1087,3,20,28,32,36,46

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

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

Теория

CSV (Comma-Separated Values) – это текстовый формат, который используется для представления табличных данных. В данном случае, файл содержит строки, каждая из которых состоит из семи чисел, разделённых запятыми. Первая колонка представляет собой идентификатор строки и должна оставаться без изменений, тогда как остальные значения должны быть отсортированы по возрастанию.

Примеры инструментов

1. Perl

Perl – это мощный язык программирования, особенно подходящий для работы с текстами и строками. В приведённом ниже решении Perl используется для разбивки строки на элементы, сортировки чисел и объединения их обратно в строку.

perl -F, -lape '$_ = join ",", shift @F, sort {$a <=> $b} @F' < input.csv

Объяснение:

  • -F, указывает Perl разбивать входные данные на массив @F, используя запятую как разделитель.
  • -lape последовательно обрабатывает каждую строку, разделяет строку, сортирует, а затем объединяет элементы.
  • $_ = join ",", shift @F, sort {$a <=> $b} @F выполняет сортировку элементов со второго по последний, оставляя первый элемент (идентификатор) на месте.

2. GNU Awk

GNU Awk – это текстовый процессор, который хорошо подходит для обработки и анализа текстов.

gawk -F, '
  {
    split($0, a)
    printf "%s", a[1]
    delete a[1]
    n = asort(a)
    for (i = 1; i <= n ; i++) printf "%s", FS a[i]
    print ""
  }' < input.csv

Объяснение:

  • gawk используется для работы с CSV-файлами с разделителем – запятой -F,.
  • split($0, a) разделяет текущую строку на массив a.
  • delete a[1] удаляет первый элемент из массива (идентификатор).
  • asort(a) сортирует массив от второго до последнего элемента.
  • printf и print формируют строку вывода, добавляя снова первый элемент (идентификатор) и отсортированные значения.

3. Miller (mlr)

Miller – это инструмент для обработки CSV-файлов, qui делает обработку табличных данных особенно простой с интуитивно понятным синтаксисом.

mlr --nidx --fs comma put 'for (k,v in sort(arrayify($*)[2:-1])) { $[k+1] = v }; ' input.csv

Объяснение:

  • --nidx и --fs comma говорит Miller работать с файлами, где поля не имеют заголовков и разделяются запятыми.
  • sort(arrayify($*)[2:-1]) преобразует строку в массив, сортирует его элементы начиная со второго и возвращает обратно.

Применение

Эти примеры позволяют выбрать наиболее подходящий инструмент в зависимости от среды и предпочтений. Например, если задача выполняется на сервере без установленного perl, Awk может стать отличной альтернативой. Если требуется более современный и легкий в использовании инструмент, тогда выбор может пасть на Miller.

Кроме синтаксиса и команд, важно учесть настройки локализации и обработки строки. Например, окончание строк в файлах может различаться между системами (Unix/Linux, Windows, MacOS), что потенциально может вызвать проблемы при выполнении скриптов.

В заключение, использование скриптов и утилит, таких как perl, gawk, и mlr, позволяет эффективно работать с CSV файлами, выполняя сортировку или другие операции над данными. Выбор конкретного решения должен основываться на доступности инструментов, удобстве использования и специфическом контексте задачи.

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

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