Як видалити повторювані рядки 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 для пояснення!
СС Енн

5
awk '/^[[:blank:]]*$/ { print; next; }; !seen[$0]++'

Все, що вам потрібно зробити, це спочатку перевірити чи порожній (справді порожній чи просто порожній) рядок.


5

Ось ще одне awkрішення, схоже на відповідь @ Тор, менш стисле, але більш ефективне:

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

З цим ми лише перевіряємо a[$0], чи існує чи ні. Якщо ні, ініціалізуючи його, тоді надрукуйте. У цьому випадку ми не маємо жодних посилань, присвоєнь, a[$0]якщо вони існували.


Я не вимірював значної різниці в часі з моїм тестовим файлом 288 рядків. Однак ваш код, безумовно, привертає нагороду за те, що він найбільш читається.
Серж Стротобандт
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.