Как эта команда AWK сохраняет порядок элементов массива?

63
8

Здесь список значений RGB из файла, называемого "colors.txt",

255 222 0  
101 153 255
255 153 0
13 112 84
13 112 84
255 222 0
13 112 84
9 112 84

Я могу использовать массив awk для получения 5 уникальных комбинаций RGB из файла с помощью

awk '{arr[($1","$2","$3)]} END {for (i in arr) print i}' colors.txt

Это дает:

9,112,84  
255,222,0
13,112,84
255,153,0
101,153,255

Обратите внимание, что они не в том порядке, в котором они были во входном файле. Однако эта команда

awk 'arr[($1","$2","$3)]++==0 {print ($1","$2","$3)}' colors.txt

255,222,0
101,153,255
255,153,0
13,112,84
9,112,84

сохраняет порядок. Как именно это работает? Я нашел вторую версию команды здесь.

спросил(а) 2021-01-25T22:19:46+03:00 4 месяца, 3 недели назад
1
Решение
116

Просто для удовольствия можно было бы объединить его в неловкое:

awk '!A[$1=$1,$2,$3]++' OFS=, file

ответил(а) 2021-01-25T22:19:46+03:00 4 месяца, 3 недели назад
98

Эта строка:

awk '{arr[($1","$2","$3)]} END {for (i in arr) print i}' colors.txt

печатает хэш после того, как вы прочитали все входные данные, а так как хеш-ключи не сохраняют порядок, выходной результат является довольно произвольным.

Эта команда:

awk 'arr[($1","$2","$3)]++==0 {print ($1","$2","$3)}' colors.txt

Проверяет, была ли одна и та же комбинация ранее напечатана с использованием хэша, однако она сразу же печатает ввод, если arr[($1","$2","$3)] равно нулю. Таким образом, нет сохранения заказа. Это больше похоже на немедленную печать.

ответил(а) 2021-01-25T22:19:46+03:00 4 месяца, 3 недели назад
99

perreal объяснил, почему заказ сохранен, я хотел затронуть некоторые из тонкостей этой идиомы:

    Если в сценарии встречается только один массив, я обычно использую hash или h чтобы он напоминал себе его тип. Подстроки массивов, разделенных запятой, уже работают как ожидается в gawk и nawk, т. nawk h[$1,$2,$3] становится h[$1 SUBSEP $2 SUBSEP $3]. Значение SUBSEP умолчанию - \034 или 0x1c. Я нахожу !h[...]++ более читабельным, чем h[...]++==0, может быть, это только я. Я предпочитаю использовать OFS над явной печатью, то есть $1=$1; print $1=$1; print над print ($1","$2","$3).

Все это вместе взятое:

awk '!h[$1,$2,$3]++ { $1=$1; print }' OFS=',' colors.txt

ответил(а) 2021-01-25T22:19:46+03:00 4 месяца, 3 недели назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема