AWK - печатать только дубликаты

У меня есть файл:

jeden
dwa
jeden
trzy
trzy
cztery
piec
jeden

Эта команда выводит:

$ awk 'BEGIN {while ((getline < "file") > 0) if(a[$0]++) print }'
jeden
trzy
jeden

Я хочу распечатать все дубликаты:

jeden
jeden
trzy
trzy
jeden

ИЗМЕНИТЬ:

Я нашел пример, который работает.

awk '{if (x[$1]) { x_count[$1]++; print $0; if (x_count[$1] == 1) { print x[$1] } } x[$1] = $0}' file

Я хочу сделать то же самое, но с getline.


person Tedee12345    schedule 07.05.2012    source источник
comment
Другой: sort file | uniq -D   -  person kev    schedule 07.05.2012
comment
Почему вы хотите использовать getline?   -  person Kevin    schedule 08.05.2012
comment
@Kevin, потому что мне это понадобится в сценарии.   -  person Tedee12345    schedule 08.05.2012


Ответы (3)


awk 'BEGIN {while ((getline < "file") > 0) { a[$0]++; if(a[$0] == 2) print; if (a[$0] >= 2) print }}'

Когда счетчик равен двум, он печатает строку. Когда счетчик больше или равен двум, он печатает строку. Таким образом, во втором случае строка печатается дважды, чтобы «наверстать упущенное».

person Dennis Williamson    schedule 08.05.2012
comment
@Tedee12345: Обратите внимание, что это может немного повлиять на порядок. - person Dennis Williamson; 08.05.2012
comment
@ Деннис Уильямсон Можете ли вы привести пример на эту тему? - person Tedee12345; 08.05.2012
comment
@Tedee12345: Если бы у вас были a, b, b, a, например, b был бы напечатан перед a. Однако это может быть нежелательно. - person Dennis Williamson; 08.05.2012
comment
@ Деннис Уильямсон Теперь я понимаю. Спасибо тебе за пояснение. - person Tedee12345; 08.05.2012

Вам нужно либо сохранить все строки в памяти, либо выполнить второй проход по файлу. Вероятно, проще сделать первое, и, если это не массивный файл, у вас, вероятно, есть память для него. Можно, конечно, впихнуть это в одну строку, но для простоты понимания вот в виде файла.

#!/usr/bin/awk -f

{ 
        lines[NR] = $0
        counts[$0]++ 
}             

END { 
        for(i = 0; i < length(lines); i++) {
                if(counts[lines[i]] > 1) {
                        print lines[i]
                }       
        }       
}

Кроме того, ваш оригинал будет более кратко написан следующим образом:

$ awk 'a[$0]++' file
person Kevin    schedule 07.05.2012

Это может сработать для вас:

awk '{a[$1]++}END{for(x in a)if(a[x]>1)for(i=1;i<=a[x];i++)print x}' file
person potong    schedule 07.05.2012
comment
Похоже, он хочет, чтобы линии были в порядке. - person Kevin; 07.05.2012