Xử lý 3 tập tin bằng awk


9

Xem xét các tệp sau:

file1:

boo,8,1024
foo,7,2048

file2:

foo,0,24,154
noo,0,10,561

file3:

24,154,7,1024,0

Những gì tôi cần là đi đến File1 và kiểm tra xem $2==7; nếu đúng, mất $1, $2$3từ File1 ; bây giờ tôi phải so sánh nếu $1từ File1 bằng để $1từ File2 ; nếu đúng, tôi phải đi $3$4từ File2 mà không tồn tại trong File1 , sau đó tôi phải đi đến file3 và kiểm tra xem $1từ file3 bằng $3từ File2 , và $2từ file3 bằng $4từ File2 ; nếu có, thì tôi phải kiểm tra nếu $2từ File1tương đương với $3từ file3 , sau đó nếu tình trạng này là sự thật, tôi phải so sánh $3từ File1 với $4từ file3 , nếu $3từ File1 là hơn $4từ file3 .

Tôi đã thử đoạn script sau:

cat [file1] [file2] [file3] | 
awk -F, 
'{if(NF==3)
    {if($2==7){a[$1]=$1; b[$1]=$2; c[$1]=$3}
    }else
        {if(NF==4){if(a[$1]==$1){d[$3]=$3; e[$4]=$4}
                  }else
                        {if(NF==5){if(d[$1]==$1 && e[$2]==$2){print a[$1], b[$1], c[$1], d[$1]}}
                        }
                  }

  }'

Đầu ra mong muốn là:

foo,7,2048,24,154,1024

Câu trả lời:


9

Điều đó làm việc cho tôi:

awk -F, 'FNR==1{++f} \
  f==1 && $2==7 {a1[$1]++; a2[$2]=$3; o=$0} \
  f==2 && a1[$1] {o=o","$3","$4; a3[$3]=$4} \
  f==3 && a3[$1] && $2==a3[$1] && a2[$3] && $4<a2[$3] {print o}' \
file1 file2 file3

Giải thích :

  • Dòng đầu tiên ( FNR==1{++f}) tăng chỉ mục tệp để sau đó xác định tệp nào chúng ta là 1-3.
  • file1: nếu $2bằng7
    • điền vào một mảng a1với $1chỉ mục và a2với $2chỉ mục và $3dưới dạng giá trị
    • ghi lại obiến (đầu ra) với 3 trường đầu tiên
  • file2: nếu $1của file2bình đẳng $1của file1(prevously viết bằng a1)
    • nối $3$4biến đầu ra o.
    • điền vào một mảng a3với $3chỉ mục và $4giá trị.
  • tập tin 3: nếu:
    • $1bằng file2s $3(chỉ mục của a3)
    • $2bằng file2s $4(giá trị của a3)
    • $3bằng file1s $2(chỉ mục của a2)
    • $4thấp hơn file1s $3(giá trị của a2)
  • sau đó:
    • in giá trị của o.

Có cần phải gạch chéo ngược (ngoài lần cuối) không? BEGINFILE (thay vì FNR == 1) thì sao?
Archemar

@Archemar BEGINFILE và ENDFILE là phần mở rộng gawk và backslashes tất cả có thể được gỡ bỏ, tôi inseted họ, cho readablility tốt hơn: bạn có thể viết rằng toàn bộ điều trong một dòng duy nhất, nhưng nó sẽ không nhìn đẹp
hỗn loạn

@chaos, cảm ơn bạn, nhưng tiếc là nó luôn trả về null.
Eng7

@ Azizieh7 Tôi đã thử nghiệm nó với mawk và gawk với 3 tệp ví dụ đầu vào của bạn. Đối với tôi nó đã làm việc. Bạn có sử dụng các tệp đầu vào hoặc mã hóa / ngắt dòng khác nhau không?
hỗn loạn

@chaos, có các dòng ngắt khác nhau trong tệp3, nhưng tôi sử dụng tr -d '\ 015' để khắc phục điều này.
Eng7

1

Giải pháp TXR:

@(repeat)
@id,@val0,@val1
@  (next)
@  (skip)
@id,@nil,@val2,@val3
@  (next)
@val2,@val3,@val0,@val4,@val5
@  (require (< (int-str val4) (int-str val1)))
@  (output)
@id,@val0,@val1,@val2,@val3,@val4
@  (end)
@(end)

Chạy:

$ txr join.txr file1 file2 file3
foo,7,2048,24,154,1024

Nhưng người quan sát sắc sảo sẽ lưu ý rằng 7 chưa được chỉ định ở bất kỳ đâu trong mã, xuất hiện ngay ở đầu ra! Đó là bởi vì mã thực sự diễu hành qua tất cả các bản ghi trong file1in tất cả các kết hợp đáp ứng các kết quả khớp và ràng buộc . Là người duy nhất trong các dữ liệu mẫu là một với val0việc 7.

Nếu có nhiều kết hợp được tìm thấy, nó có thể bị hạn chế chỉ 7một kết hợp như thế này:

$ txr -Dval0=7 join.txr file1 file2 file3
foo,7,2048,24,154,1024

# how about 6?
$ txr -Dval0=6 join.txr file1 file2 file3
# no output

Ngôn ngữ trích xuất mẫu TXR cung cấp ở đây một mẫu khớp lớn với các tham chiếu ngược ẩn thông qua việc lặp lại các tên biến, trải rộng nhiều tệp, với các mẫu trích xuất nhiều dòng và các ràng buộc phi văn bản, cộng với các hiệu ứng phụ được nhúng như đầu ra, v.v. .

Giải pháp Awk được chấp nhận đã dịch cẩn thận awkmacro TXR Lisp :

(awk (:begin (set fs "," ofs ","))
     (:let o (a1 (hash :equal-based)) (a2 (hash)) (a3 (hash)))
     (t (mf [orf int-str identity])) ;; map those fields to integers, which can be
     ((and (= arg 1) (= [f 1] 7)) (inc [a1 [f 0] 0])
                                  (set [a2 [f 1]] [f 2])
                                  (set o rec))
     ((and (= arg 2) [a1 [f 0]]) (set o `@o,@[f 2],@[f 3]`)
                                 (set [a3 [f 2]] [f 3]))
     ((and (= arg 3)
           [a3 [f 0]]
           (= [f 1] [a3 [f 0]])
           [a2 [f 2]]
           (< [f 3] [a2 [f 2]])) (prn o)))

Chạy:

$ txr awkit.tl file1 file2 file3
foo,7,2048,24,154

Phần ,1024bắt buộc trong đầu ra bị thiếu; "Awk Classic" ban đầu có hành vi này.

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.