Как найти уникальные значения на основе двух столбцов с помощью awk - PullRequest
0 голосов
/ 06 мая 2019

Считайте, что у меня есть тестовый файл (test.txt), содержащий данные как

1,2 
2,3 
2,1 
2,2 
3,1 
1,3 
2,5
4,1

Я хочу удалить дубликаты на пару, скажем, для пары (1,2) и (2,1) должен быть напечатан любой из них (печать «первым пришел - первым был напечатан»). Ожидаемый результат -

1,2
2,3
3,1
2,2
2,5
4,1

Я пробовал эту команду, awk -F"," '!seen[$1,$2]++ && !seen[$2,$1]' test.txt. Она печатается как

1,2
2,3
3,1
2,5
4,1

Почему пара 2,2 не печатает? Также как получить ожидаемый результат.

Ответы [ 4 ]

2 голосов
/ 06 мая 2019

Как уже говорилось, проблема заключается в коротком замыкании в логической оценке.

Чтобы обойти это, можно проверить и установить одно единственное значение в 2D-таблице seen:

awk -F"," '!seen[($1<$2?$1:$2)+0, ($1>$2?$1:$2)+0]++'

В основном он использует минимум и максимум двух значений в качестве индексов, следовательно, один тест вместо двух, а затем увеличивает интервал.

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

1 голос
/ 07 мая 2019

Распространенное идиоматическое решение с двумя полями для любого awk в любой оболочке на любом компьютере UNIX:

$ awk -F, '!seen[$1>$2 ? $1 FS $2 : $2 FS $1]++' file
1,2
2,3
2,2
3,1
2,5
4,1

и для любого количества полей, использующих GNU awk для asort():

awk -F, '{split($0,a); asort(a); for (i=1;i<=NF;i++) k=(i>1 ? k FS : "") a[i]} !seen[k]++' file

например, для входного файла, содержащего каждую перестановку 1,2,3 и 2,3,4:

$ cat file
1,2,3
1,3,2
2,1,3
2,3,1
3,1,2
3,2,1
2,3,4
2,4,3
3,2,4
3,4,2
4,2,3
4,3,2

$ awk -F, '{split($0,a); asort(a); for (i=1;i<=NF;i++) k=(i>1 ? k FS : "") a[i]} !seen[k]++' file
1,2,3
2,3,4
0 голосов
/ 06 мая 2019

Если порядок не важен, вы можете легко использовать комбинацию awk , sort и uniq .

awk -F "," '$1 < $2 { printf "%d,%d\n", $1,$2} $2 <= $1 {printf "%d,%d\n", $2, $1}' file | sort | uniq

Действия awk здесь нормализуют вывод, сортируя числа так, что 2,1 станет 1,2

0 голосов
/ 06 мая 2019

Я не хорош в awk, но это легко сделать с помощью других инструментов.

Если порядок не имеет значения, давайте продублируем каждую строку с обратным порядком. Тогда мы можем просто использовать sort -u для печати уникальных строк:

cat <<EOF |
1,2
2,3
2,1
2,2
3,1
1,3
2,5
4,1
EOF
sed 's/\(.*\),\(.*\)/\1,\2:\1,\2\n\2,\1:\1,\2/' | 
sort -u -t: -k1,1 |
cut -d: -f2 |
sort -u

Преобразование sed utlity:

 1,2

в:

 1,2:1,2
 2,1:1,2

Затем я удаляю дубликаты, используя первый столбец, отделенный только : с sort -u -t: -k1,1. Затем cut -d: -f2 удаляет первый столбец. Затем я снова сортирую уникальные строки, потому что у нас будут дубликаты (например, когда 1,2 уникален как для 1,2, так и 2,1). Результат:

1,2
2,2
2,3
2,5
3,1
4,1
...