2-уровневая сортировка массива awk

У меня есть этот входной файл ниже, где разделитель полей ir "+", который я хочу отсортировать на уровне 2. Сначала по 3-му полю, а затем по 2-му полю в порядке возрастания.

Вход

240x151+140+624
240x151+462+176
240x151+87+257
240x151+366+355
240x151+77+448
240x151+468+542
178x59+223+65
178x59+417+65
178x59+611+65
178x59+29+65
110x16+255+63

Мой код, который у меня есть до сих пор, ниже, но вывод не то, что мне нужно.

awk '{split($0,f,"+")
      a[$0]=f[3];
     }END{
          n=asorti(a,b)
          for (i=1;i<=n;i++) 
          print b[i]}' file.txt
110x16+255+63
178x59+223+65
178x59+29+65
178x59+417+65
178x59+611+65
240x151+140+624
240x151+366+355
240x151+462+176
240x151+468+542
240x151+77+448
240x151+87+257

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

110x16+255+63  
178x59+29+65   
178x59+223+65  
178x59+417+65  
178x59+611+65  
240x151+462+176
240x151+87+257 
240x151+366+355
240x151+77+448 
240x151+468+542
240x151+140+624

person Ger Cas    schedule 29.10.2018    source источник
comment
для этого в awk создайте новый ключ, объединив 3-е и 2-е поля и отсортировав по этому ключу. Однако вам не нужно этого делать, так как sort уже предназначен для обработки таких случаев.   -  person karakfa    schedule 29.10.2018


Ответы (2)


sort подходит для этого

$ sort -t+ -k3n -k2,2n file

110x16+255+63
178x59+29+65
178x59+223+65
178x59+417+65
178x59+611+65
240x151+462+176
240x151+87+257
240x151+366+355
240x151+77+448
240x151+468+542
240x151+140+624

один из способов сделать это в awk путем создания нового ключа путем объединения 3-го и 2-го полей и сортировки по этому ключу. Обратите внимание, однако, что индексы массива будут отсортированы нечислово. Итак, мы должны преобразовать их в эквивалентный текстовый формат, отсортировав его нулями. Предполагая, что наибольшее число имеет 5 цифр (если не изменить соответственно).

$ awk -F+ '{k1=sprintf("%05d",$3); k2=sprintf("%05d",$2); a[k1,k2]=$0}
       END {n=asorti(a,d); for(i=1;i<=n;i++) print a[d[i]]}' file

110x16+255+63
178x59+29+65
178x59+223+65
178x59+417+65
178x59+611+65
240x151+462+176
240x151+87+257
240x151+366+355
240x151+77+448
240x151+468+542
240x151+140+624
person karakfa    schedule 29.10.2018
comment
Спасибо за Ваш ответ. Я закончил с сортировкой, но, поскольку это часть другого скрипта, мне нужно дважды выполнить конвейер. Сначала читаем файл, затем передаем команду sort, а затем снова передаем команду awk, чтобы обработать результат сортировки. Я хочу использовать для этого уникальную программу awk. Не могли бы вы показать мне, как можно объединить поля 3 и 2 в качестве ключа? - person Ger Cas; 29.10.2018
comment
Почему вы думаете, что лишние трубы - это проблема? awk изначально не имел функции sort. - person karakfa; 29.10.2018
comment
Отличная каракфа, хороший очень красивый трюк и комбинация с асорти(). Большое спасибо за помощь. Я спрашивал 4 раза, как это сделать, и с 4-й попытки вы получаете решение. - person Ger Cas; 30.10.2018

Другой (не идеальный) с использованием GNU awk и asorti() третий строковый аргумент для управления сравнением элементов массива:

awk '
{
    split($0,f,"+")
    a[$0]=f[3]                    # a["110x16+255+63"] = 63
}
END {
    OFS=", "                      # for pretty output
    n=asorti(a,a,"@val_num_asc")  # NOTICE THE THIRD ARGUMENT, using asorti but "@val..."
    for (i=1;i<=n;i++)            # "@ind..." would sort using the index
        print i,a[i]              # I wrote a over old a but you could use b
}' file

Выход:

1, 110x16+255+63
2, 178x59+417+65
3, 178x59+611+65
4, 178x59+29+65
5, 178x59+223+65
6, 240x151+462+176
7, 240x151+87+257
8, 240x151+366+355
9, 240x151+77+448
10, 240x151+468+542
11, 240x151+140+624

При использовании "@ind_num_asc" порядок будет таким:

1, 110x16+255+63
2, 178x59+223+65
3, 178x59+29+65
4, 178x59+417+65
5, 178x59+611+65
6, 240x151+140+624
7, 240x151+366+355
8, 240x151+462+176
9, 240x151+468+542
10, 240x151+77+448
11, 240x151+87+257
person James Brown    schedule 30.10.2018
comment
Привет, Джеймс. Превосходно. Еще более простое решение. Я понимаю, как на первом уровне сортируется 3-е поле, но я не вижу ясно, как сортируется одинаково по возрастанию 2-е поле. - person Ger Cas; 30.10.2018
comment
Я говорил слишком рано. Кажется, ваше решение по-прежнему не печатает желаемый результат. - person Ger Cas; 30.10.2018