1

У меня есть следующий пример формата ввода (файл или стандартный ввод):

key1: 1
key2: 2
key3: 3
key1: 4
key2: 5
key3: 6

Есть ли несколько лайнеров, которые могут группировать значения по ключу, а затем сортировать?

Ожидаемый результат будет любой из таблиц:

key1 key2 key3
1    2    3
4    5    6

который впоследствии можно отсортировать по столбцу (например, sort -k2). Аналогично этому примеру.

Или в аналогичном формате, например:

key1: 1 4
key2: 2 5
key3: 3 6

Какой самый простой способ добиться этого преобразования?

2 ответа2

2

Кажется, работа для awk . Это позволяет как-то использовать ассоциативные многомерные массивы.
Следующий скрипт bash должен сделать эту работу.

awk ' { Nb[$1]++;b[$1][Nb[$1]]=$2 }       
      END{ for (i in Nb) {                
        printf("%s ", i);               
        for (j = 1 ; j<=Nb[i]; j++) printf("%ld ", b[i][j]);
       printf(" \n") ; }   
      }' aaa.txt  | sort

Некоторые заметки:

  • В первой части {...} он сканирует весь внешний файл aaa.txt и загружает массивы b[][] и количество вхождений для каждого ключа Nb[] (возможно, у вас есть 4 экземпляра key3 и 12 из key1 ...).

  • В части END{...} для каждого ключа, найденного for (i in Nb) выведите ключ без перевода строки (printf(...)), а затем для каждой записи с индексом 1 ..Nb [i], он напечатает значение. Наконец, напечатайте новую строку.

  • Финальная труба | отсортирует вывод

    key1: 1 4  
    key2: 2 5  
    key3: 3 6
    
  • Конечно, если нужны разные макеты, их можно построить, начиная с приведенного выше примера и меняя порядок размещения циклов for.

0

Когда список ключей фиксирован, его можно транспонировать следующей командой:

$ pr -mt <(grep key1 in.txt | cut -f2 -d:) <(grep key2 in.txt | cut -f2 -d:) <(grep key3 in.txt | cut -f2 -d:) | sort -k1
1            2           3
4            5           6

Это может быть улучшено еще больше, чтобы сделать его более гибким с помощью eval.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .