Видаліть сусідні дублікати рядків, зберігаючи замовлення


11

У мене є файл з одним стовпцем з іменами, які повторюються кілька разів кожен. Я хочу конденсувати кожне повторення в одне, зберігаючи будь-які інші повтори з тим самим іменем, які не суміжні з іншими однойменними повторами.

Наприклад, я хочу повернути ліву сторону в праву сторону:

Golgb1    Golgb1    
Golgb1    Akna
Golgb1    Spata20
Golgb1    Golgb1
Golgb1    Akna
Akna
Akna
Akna
Spata20
Spata20
Spata20
Golgb1
Golgb1
Golgb1
Akna
Akna
Akna

Це те, що я використовував: perl -ne 'print if ++$k{$_}==1' file.txt > file2.txt Однак цей метод зберігає лише одного представника зліва (тобто Golb1 та Akna не повторюються).

Чи є спосіб зберегти унікальні імена для кожного блоку, зберігаючи імена, які повторюються в декількох, не сусідніх блоках?

Відповіді:


23

uniq зробить це за вас:

$ uniq inputfile
Golgb1
Akna
Spata20
Golgb1
Akna

2
Ух, це було бентежно легко! Дякую!
Вік87

@ Age87 Unix - це чудово! Це працює лише тому, що ви очікуєте, що дублікати вже будуть суміжними (або не бажаєте видаляти не сусідні). Як правило, рекомендується використовуватиsort | uniq
jpaugh

1
Або ще більш лаконічно, sort -u(:
DopeGhoti


6

Спробуйте це - збережіть попередній рядок і порівняйте з поточним рядком

$ perl -ne 'print if $p ne $_; $p=$_' ip.txt
Golgb1
Akna
Spata20
Golgb1
Akna

Ви також позначили тег uniq- ви пробували?

$ uniq ip.txt
Golgb1
Akna
Spata20
Golgb1
Akna

1

З sed це можна зробити так:

sed -e '$!N;/^\(.*\)\n\1$/!P;D' input_file

Тут ми маємо в просторі шаблону в будь-який час 2 рядки. Коли порівняння між ними не вдається, ми роздруковуємо перший і рубаємо його спереду, повертаємось назад і додаємо наступний рядок у пробіл малюнка. Промийте ... повторіть

Використовуючи Perl в режимі slurp, ми розглядаємо весь файл як один довгий рядок, на який застосовано регулярний вираз, який робить порівняння для вас.

perl -0777pe 's//$1/ while /^(.*\n)\1+/gm' input_file

0

Питання про сед-рішення Ракеш Шарма.

Що робити, якщо у вас є вхідний файл, такий як:

-126.1 48.206
-126.106 48.21
-126.11 48.212
-126.114 48.214
-126.116 48.216
-126.118 48.216
-126.128 48.222
-126.136 48.226

І ви хочете, щоб вихідний файл був:

-126.1 48.206
-126.106 48.21
-126.11 48.212
-126.114 48.214
-126.116 48.216
-126.128 48.222
-126.136 48.226

Зверніть увагу на відсутні:

-126.118 48.216

Я знаю, що команда, яку я хочу, схожа на ваше рішення:

sed -e '$!N;/^\(.*\)\n\1$/!P;D' input_file

Неможливо змінити його правильним способом для друку обох стовпців, а лише сортувати таким спеціальним чином зі значеннями стовпця 2. Якісь поради?


sed -e '$!N' -e '/.*\.\([0-9]*\)\n.*\.\1$/!{P;D;}' -e 's/\n.*//;s/^/\n/;D' видалить наступні повторювані елементи. Примітка. Це вимагає GNU sed. Для POSIXповедінки вона потребує незначної перебудови.
Ракеш Шарма
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.