Loại bỏ các dòng trùng lặp liền kề trong khi giữ trật tự


11

Tôi có một tệp có một cột với các tên lặp lại một số lần mỗi cột. Tôi muốn ngưng tụ mỗi lần lặp lại thành một, trong khi vẫn giữ bất kỳ sự lặp lại nào khác có cùng tên không liền kề với các lần lặp khác cùng tên.

Ví dụ: tôi muốn xoay bên trái sang bên phải:

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

Đây là những gì tôi đã sử dụng: perl -ne 'print if ++$k{$_}==1' file.txt > file2.txt Tuy nhiên, phương pháp này chỉ giữ một đại diện từ bên trái (tức là Golb1 và Akna không được lặp lại).

Có cách nào để giữ các tên duy nhất cho mỗi khối, trong khi vẫn giữ các tên lặp lại trong nhiều khối không liền kề không?

Câu trả lời:


23

uniq sẽ làm điều này cho bạn:

$ uniq inputfile
Golgb1
Akna
Spata20
Golgb1
Akna

2
wow thật dễ dàng! cảm ơn!
Tuổi87

@ Age87 Unix thật tuyệt! Điều này chỉ hoạt động vì bạn mong muốn các bản sao liền kề, đã (hoặc, không muốn loại bỏ những cái không liền kề). Thông thường, khuyến nghị là sử dụngsort | uniq
jpaugh

1
Hoặc ngắn gọn hơn, sort -u(:
DopeGhoti

9

Awk giải pháp:

awk '$1 != name{ print }{ name = $1 }' file.txt

Đầu ra:

Golgb1
Akna
Spata20
Golgb1
Akna

6

Hãy thử điều này - lưu dòng trước đó và so sánh với dòng hiện tại

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

Bạn cũng đã gắn thẻ uniq- bạn đã thử chưa?

$ uniq ip.txt
Golgb1
Akna
Spata20
Golgb1
Akna

1

Với sed nó có thể được thực hiện như sau:

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

Ở đây chúng ta có trong không gian mẫu bất cứ lúc nào 2 dòng. Khi so sánh giữa chúng thất bại, chúng tôi in cái đầu tiên và cắt nó từ phía trước và quay lại và nối dòng tiếp theo vào không gian mẫu. Rửa ... lặp lại

Sử dụng Perl trong chế độ slurp, chúng tôi coi toàn bộ tệp là một chuỗi dài mà regex được áp dụng để so sánh với bạn.

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

0

Câu hỏi về giải pháp sed của Rakesh Sharma.

Điều gì xảy ra nếu bạn có một tệp đầu vào, chẳng hạn như:

-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

Và bạn muốn một tệp đầu ra là:

-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

Lưu ý thiếu:

-126.118 48.216

Tôi biết lệnh tôi muốn tương tự như giải pháp của bạn:

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

Không thể thay đổi nó theo đúng cách để in cả hai cột và chỉ được sắp xếp theo cách đặc biệt này với các giá trị cột 2. Bất cứ lời khuyên?


sed -e '$!N' -e '/.*\.\([0-9]*\)\n.*\.\1$/!{P;D;}' -e 's/\n.*//;s/^/\n/;D' sẽ xóa các yếu tố lặp lại tiếp theo. Lưu ý: Điều này đòi hỏi GNU sed. Đối với POSIXhành vi, nó cần thay đổi một chút.
Rakesh Sharma
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.