2009-07-12 32 views
8

Làm cách nào để thực hiện hành động trên tất cả các nhóm phù hợp khi mẫu khớp với nhiều lần trong một dòng?awk trích xuất nhiều nhóm từ mỗi dòng

Để minh họa, tôi muốn tìm kiếm /Hello! (\d+)/ và sử dụng các con số, ví dụ, in chúng ra hoặc tổng hợp, vì vậy cho đầu vào

abcHello! 200 300 Hello! Hello! 400z3 
ads 
Hello! 0 

Nếu tôi đã quyết định in chúng ra, tôi mong đợi đầu ra của

200 
400 
0 
+0

cho nhân viên của Google: lưu ý rằng với 'gawk', aka. "GNU awk", bạn thực sự có thể làm những gì tiêu đề nói (không phải là câu hỏi) trong một dòng (ví dụ: thông qua. Piping): '| gawk -v RS = '' '{in gensub (/()() /, "\\ 1 \\ 2", "g"); } '': D Điều này hỗ trợ đa dòng (do' -v RS =' '') và các nhóm con phù hợp (do sử dụng gensub' của gawk) !!! – Andrew

Trả lời

10

Đây là một cú pháp đơn giản, và mỗi awk (nawk, mawk, trố mắt, vv) có thể sử dụng điều này.

{ 
    while (match($0, /Hello! [0-9]+/)) { 
     pattern = substr($0, RSTART, RLENGTH); 
     sub(/Hello! /, "", pattern); 
     print pattern; 
     $0 = substr($0, RSTART + RLENGTH); 
    } 
} 
1

GNU awk

awk 'BEGIN{ RS="Hello! ";} 
{ 
    gsub(/[^0-9].*/,"",$1) 
    if ($1 != ""){ 
     print $1 
    } 
}' file 
+0

Đẹp, nhưng sẽ không hoạt động đối với các mẫu phức tạp hơn như/([a-g] + | [h-z] +)/và sẽ so khớp trên một linefeed. –

+0

bạn có thể cung cấp một ví dụ không? – ghostdog74

0

Đây làCú pháp. Nó cũng làm việc cho mẫu khi không có văn bản cố định mà có thể làm việc như một tách hồ sơ và không phù hợp trên linefeeds:

{ 
    pattern = "([a-g]+|[h-z]+)" 
    while (match($0, pattern, arr)) 
    { 
     val = arr[1] 
     print val 
     sub(pattern, "") 
    } 
} 
0

Không có hàm gawk nào phù hợp với cùng một mẫu nhiều lần trong một dòng. Trừ khi bạn biết chính xác số lần lặp lại mẫu đó.

Có điều này, bạn phải lặp lại "thủ công" trên tất cả các kết quả phù hợp trong cùng một dòng. Ví dụ đầu vào của bạn, nó sẽ là:

{ 
    from = 0 
    pos = match($0, /Hello! ([0-9]+)/, val) 
    while(0 < pos) 
    { 
    print val[1] 
    from += pos + val[0, "length"] 
    pos = match(substr($0, from), /Hello! ([0-9]+)/, val) 
    } 
} 

Nếu mẫu phải phù hợp trên một linefeed, bạn phải thay đổi các dấu phân cách kỷ lục đầu vào - RS

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