Xóa toàn bộ hàng trong một tệp nếu cột đầu tiên được lặp lại


7

Tôi có một tệp chứa hai cột và 10 triệu hàng. Cột đầu tiên chứa nhiều giá trị lặp lại, nhưng có một giá trị riêng biệt trong cột 2. Tôi muốn xóa các hàng lặp lại và chỉ muốn giữ một giá trị sử dụng awk. Lưu ý: tệp được sắp xếp với các giá trị trong cột 1. Ví dụ:

1.123 -4.0
2.234 -3.5
2.234 -3.1
2.234 -2.0
4.432 0.0
5.123 +0.2
8.654 +0.5
8.654 +0.8
8.654 +0.9
.
.
.
.

Sản lượng dự kiến

1.123 -4.0
2.234 -3.5
4.432 0.0
5.123 +0.2
8.654 +0.5
.
.
.
.

Bạn có thể thấy câu hỏi gần đây hữu ích unix.stackexchange.com/q/159695/65304
Steeldo

3
Đơn giản:sort -buk1,1
Stéphane Chazelas

Câu trả lời:


14

Một vài cách:

  1. ôi

    awk '!a[$1]++' file

    Đây là một cách viết rất cô đọng này:

    awk '{if(! a[$1]){print; a[$1]++}}' file

    Vì vậy, nếu trường đầu tiên hiện tại ( $1) không nằm trong amảng, hãy in dòng và thêm trường thứ 1 vào a. Lần sau chúng ta thấy trường đó, nó sẽ nằm trong mảng và do đó sẽ không được in.

  2. Perl

    perl -ane '$k{$F[0]}++ or print' file

    hoặc là

    perl -ane 'print if !$k{$F[0]}++' file

    Điều này về cơ bản là giống như awkmột. Các -nnguyên nhân perl để đọc dòng tệp đầu vào theo dòng và áp dụng tập lệnh được cung cấp -echo mỗi dòng. Các -asẽ tự động tách mỗi dòng trên khoảng trắng và lưu các lĩnh vực kết quả là @Fmảng. Cuối cùng, trường đầu tiên được thêm vào %khàm băm và nếu nó chưa có ở đó, dòng được in. Điều tương tự có thể được viết là

    perl -e 'while(<>){
                @F=split(/\s+/); 
                print unless defined($k{$F[0]}); 
                $k{$F[0]}++;
             }' file
    
  3. Coreutils

    rev file | uniq -f 1 | rev

    Phương pháp này hoạt động bằng cách trước tiên đảo ngược các dòng filesao cho nếu một dòng là 12 345 thì bây giờ sẽ là 543 21. Sau đó, chúng ta sử dụng uniq -f 1để bỏ qua trường đầu tiên, nghĩa là cột 543 nằm trong. Có các trường trong file. Sử dụng uniqở đây có tác dụng lọc ra bất kỳ dòng trùng lặp nào, chỉ giữ lại mỗi dòng. Cuối cùng, chúng tôi đặt các dòng trở lại trật tự ban đầu của họ với một đảo ngược khác.

  4. Sắp xếp GNU (theo đề xuất của @ StéphaneChazelas)

    sort -buk1,1

    Các -bcờ lờ hàng đầu khoảng trắng và các -uphương tiện in ruộng chỉ độc đáo. Các bit thông minh là -k1,1. Các -klá cờ đặt trường để sắp xếp trên. Nó có định dạng chung -k POS1[,POS2]có nghĩa là chỉ nhìn vào các trường POS1thông qua POS2 khi sắp xếp. Vì vậy, -k1,1có nghĩa là chỉ nhìn vào lĩnh vực 1. Tùy thuộc vào dữ liệu của bạn, bạn có thể muốn thêm một trong các tùy chọn sau:

     -g, --general-numeric-sort
          compare according to general numerical value
     -n, --numeric-sort
          compare according to string numerical value
    

Hmm, đó là những gì revđược sử dụng cho ... Cảm ơn.
lgeorget

Tôi thử giải pháp awk abovve và nhận được thông báo [: Không tìm thấy sự kiện.
Nilesh

cũng sau thông báo này khi tôi nhấn phím lên thì lệnh được đổi thành tên tệp awk '$ 1] ++'
Nilesh

@Nilesh bạn đã sao chép lệnh chính xác hay bạn đã sử dụng dấu ngoặc kép ( ") thay vì dấu ngoặc đơn ( ')?
terdon

1
@ 1_CR điểm tốt, cảm ơn. Tôi đã thêm các mô tả của hai tùy chọn có liên quan. Tôi không biết chi tiết nhưng một số thử nghiệm nhanh cho thấy rằng sort -unhanh hơn đáng kể trên dữ liệu được định sẵn, vâng.
terdon

4

Nếu cột đầu tiên luôn dài 5 ký tự, bạn chỉ cần sử dụng uniq:

uniq -w 5 file

Nếu không, sử dụng awk:

awk '$1!=a{print $0; a=$1}' file

Cái đầu tiên chắc chắn sẽ nhanh hơn với một tệp lớn.

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.