Как удалить дубликаты строк с помощью awk, сохраняя при этом пустые строки?

13

awkКоманда ниже удаляет все повторяющиеся строки, как описано здесь :

awk '!seen[$0]++'

Если текст содержит пустые строки, будут удалены все, кроме одной пустой строки.

Как сохранить все пустые строки при удалении всех непустых повторяющихся строк, используя только awk? Пожалуйста, также включите краткое объяснение.

Серж Строобандт
источник

Ответы:

28

Другой вариант - проверить NF, например:

awk '!NF || !seen[$0]++'
Тор
источник
11

альтернативно

awk '!/./ || !seen[$0]++' file

Основной трюк такой же, seen[$0]++создает в seenассоциативном массиве запись , ключом которой является текущая строка ( $0). Следовательно, !seen[$0]++будет ложным, если эта строка уже была замечена. Он /./проверяет, содержит ли строка непустые символы, и !/./сопоставляет непустые строки. В сочетании с || !seen[$0]++ним будут игнорироваться все повторяющиеся строки, кроме пустых, и выводятся остальные.

Тердон
источник
Я думаю, что это должен был быть принятый ответ. +1 за объяснение!
SS Anne
5
awk '/^[[:blank:]]*$/ { print; next; }; !seen[$0]++'

Все, что вам нужно сделать, это сначала проверить наличие пустой (действительно пустой или просто пустой) строки.

Хауке Лагинг
источник
5

Вот еще одно awkрешение, похожее на ответ @ Thor, менее сжатое, но более эффективное:

awk '!NF {print;next}; !($0 in a) {a[$0];print}' file

При этом мы только проверяем a[$0], существует или нет. Если нет, инициализируйте его, затем напечатайте. В этом случае у нас нет никаких ссылок, назначения, a[$0]если оно существовало.

cuonglm
источник
Я не измерял значительную разницу во времени с моим тестовым файлом из 288 строк. Тем не менее, ваш код, безусловно, получает приз за то, что он наиболее читаемый.
Серж Строобандт