2012-05-30 30 views
5

tôi cần phải xử lý một tệp dữ liệu lớn có chứa các hồ sơ nhiều dòng, ví dụ đầu vào:sử dụng awk để xác định kỷ lục nhiều dòng và lọc

1 Name  Dan 
1 Title  Professor 
1 Address aaa street 
1 City  xxx city 
1 State  yyy 
1 Phone  123-456-7890 
2 Name  Luke 
2 Title  Professor 
2 Address bbb street 
2 City  xxx city 
3 Name  Tom 
3 Title  Associate Professor 
3 Like  Golf 
4 Name 
4 Title  Trainer 
4 Likes  Running 

Lưu ý rằng trường số nguyên đầu tiên là độc đáo và thực sự xác định một toàn bộ hồ sơ. Vì vậy, trong đầu vào ở trên tôi thực sự có 4 hồ sơ mặc dù tôi không biết có bao nhiêu dòng thuộc tính mỗi bản ghi có thể có. Tôi cần phải: - xác định hồ sơ hợp lệ (phải có trường "Tên" và "Tiêu đề") - xuất các thuộc tính có sẵn cho mỗi bản ghi hợp lệ, nói "Tên", "Tiêu đề", "Địa chỉ" là các trường cần thiết.

Ví dụ đầu ra:

1 Name  Dan 
1 Title  Professor 
1 Address aaa street 
2 Name  Luke 
2 Title  Professor 
2 Address bbb street 
3 Name  Tom 
3 Title  Associate Professor 

Vì vậy, trong các tập tin đầu ra, kỷ lục 4 được lấy ra vì nó doen't có "Tên". Bản ghi 3 không có trường Địa chỉ nhưng vẫn đang in ra đầu ra vì đó là bản ghi hợp lệ có "Tên" và "Tiêu đề".

Tôi có thể làm điều này với awk không? Nhưng làm cách nào để tôi xác định toàn bộ bản ghi bằng cách sử dụng trường "id" đầu tiên trên mỗi dòng?

Cảm ơn rất nhiều chuyên gia về tập lệnh vỏ Unix để giúp tôi! :)

Trả lời

6

Điều này có vẻ hiệu quả. Có rất nhiều cách bạn có thể làm điều này, ngay cả trong awk.

Tôi đã định vị nó ra để đọc dễ dàng hơn.

Lưu ý rằng bản ghi 3 không hiển thị vì thiếu trường "Địa chỉ" mà bạn đã xác định là bắt buộc.

#!/usr/bin/awk -f 

BEGIN { 
     # Set your required fields here... 
     required["Name"]=1; 
     required["Title"]=1; 
     required["Address"]=1; 

     # Count the required fields 
     for (i in required) enough++; 
} 

# Note that this will run on the first record, but only to initialize variables 
$1 != last1 { 
     if (hits >= enough) { 
       printf("%s",output); 
     } 
     last1=$1; output=""; hits=0; 
} 

# This appends the current line to a buffer, followed by the record separator (RS) 
{ output=output $0 RS } 

# Count the required fields; used to determine whether to print the buffer 
required[$2] { hits++ } 

END { 
     # Print the final buffer, since we only print on the next record 
     if (hits >= enough) { 
       printf("%s",output); 
     } 
} 
+0

cảm ơn rất nhiều sự giúp đỡ của bạn! Nó đã cho tôi một chút thời gian để tiêu hóa giải pháp của bạn và sau đó tôi đã học được rất nhiều từ nó !!! :) rất cảm kích! Đã cứu tôi rất nhiều thời gian cũng như học được rất nhiều từ điều này :) – trillions

+0

không sao cả! vui vì nó hữu ích. – ghoti

+0

gần như +1 - chủ yếu là rất tốt. Bạn có thể thả mệnh đề 'NR == 1'. Câu hỏi có vẻ hơi mơ hồ về việc liệu "Địa chỉ" có bắt buộc hay không. Tuy nhiên, tôi đọc nó là * không * được yêu cầu (do đó ghi lại 3 nên được đầu ra). Khi tôi chạy kịch bản của bạn với dòng "Địa chỉ" nhận xét, tôi nhận được tất cả bốn hồ sơ thay vì chỉ 1-3, mặc dù thực tế là "Tên" là trống cho hồ sơ 4. Lý do cho điều này là chọn của bạn ' yêu cầu [$ 2] 'đưa vào sự tồn tại của một phần tử mảng tương ứng với mỗi tên trường chỉ bằng cách tham chiếu * và bạn không kiểm tra xem nó có bằng' 1' * hay không. –

3

Tôi không giỏi lúc này, nhưng tôi sẽ giải quyết vấn đề này trong Perl. Đây là một giải pháp Perl: cho mỗi bản ghi, nó ghi nhớ các dòng quan trọng và cho dù tên và tiêu đề đã được nhìn thấy. Vào cuối bản ghi, bản ghi được in nếu tất cả các điều kiện được đáp ứng.

#!/usr/bin/perl 
use warnings; 
use strict; 

my ($last, $has_name, $has_title, @record); 
while (<DATA>) { 
    my ($id, $key, $value) = split; 
    if ($id != $last and @record) { 
     print @record if $has_name and $has_title; 
     undef @record; 
     undef $has_name; 
     undef $has_title; 
    } 
    $has_name = 1 if $key eq 'Name'; 
    $has_title = 1 if $key eq 'Title'; 
    push @record, $_ if grep $key eq $_, qw/Name Address Title/; 
    $last = $id; 
} 


__DATA__ 
1 Name  Dan 
1 Title  Professor 
1 Address aaa street 
1 City  xxx city 
1 State  yyy 
1 Phone  123-456-7890 
2 Name  Luke 
2 Title  Professor 
2 Address bbb street 
2 City  xxx city 
3 Name  Tom 
3 Title  Associate Professor 
3 Like  Golf 
4 Name 
4 Title  Trainer 
4 Likes  Running 
+0

cảm ơn rất nhiều cho giải pháp perl của bạn! Tôi sẽ thử nó sau. Bây giờ tôi sẽ đi với awk kể từ khi tôi vẫn cần phải sửa đổi kịch bản một chút cho nhu cầu tiếp theo của tôi mà không được đăng ở đây. – trillions

Các vấn đề liên quan