У меня есть этот входной файл ниже, где разделитель полей 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
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
Спасибо за Ваш ответ. Я закончил с сортировкой, но поскольку это часть другого скрипта, мне нужно дважды передать по конвейеру. Сначала чтение файла, затем конвейер для команды сортировки, а затем снова конвейер для awk для обработки результирующего вывода сортировки. Я хочу использовать для этого уникальную программу awk. Не могли бы вы показать мне, как было бы объединить поля 3 и 2 в качестве ключевых?
Как вы думаете, почему дополнительные трубопроводы - это проблема? awk
изначально не имел функции sort
.
Отличная каракфа, красивый, очень красивый трюк и комбинация с асорти (). Большое спасибо за помощь. Я 4 раза спрашивал, как это сделать, и в 4-й попытке вы получили решение.
Другой (не идеальный), использующий 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
Привет, Джеймс. Превосходно. Еще более простое решение. Я понимаю, как на первом уровне сортируется 3-е поле, но я не вижу четко, как сортируется одинаково по возрастанию 2-го поля.
Я заговорил слишком рано. Кажется, ваше решение по-прежнему не выводит желаемый результат.
для этого в
awk
создайте новый ключ, объединив 3-е и 2-е поля и отсортируйте по этому ключу. Однако в этом нет необходимости, посколькуsort
уже разработан для таких случаев.