Sử dụng awk để chèn một dòng sau đầu ra N


7

Tôi có một tập tin văn bản chứa đầy một loạt dữ liệu. Tôi cần phải rút ra các dòng có chứa các chuỗi cụ thể. Tôi đã thực hiện điều này với awk bằng cách sử dụng như sau:

awk '/pattern1|pattern2|pattern3/ {print;}' infile

Sau đó tôi cần đặt một dòng mới (\ n) sau dòng thứ 3. Vì vậy, nó sẽ cần phải trông như thế này

pattern1
pattern2
pattern3
<new line>
pattern1...

Tôi đã có thể thực hiện điều này bằng cách chuyển lệnh đầu tiên sang một câu lệnh awk khác

awk -F '\n' '/pattern1|pattern2|pattern3/ { print; }' infile | awk '{ if ((NR % 3) == 1) printf("\n"); print; }'

Tôi nghĩ rằng phải có một cách hiệu quả hơn để làm điều này vì vậy tôi bắt đầu tìm cách xem làm thế nào tôi có thể kết hợp hai lệnh lại với nhau. Tôi đã thử như sau:

awk '/pattern1|pattern2|pattern3/ { if ((NR % 3) ==1 ) printf("\n"); print; }'

Tôi hình dung điều này sẽ hoạt động nhưng đầu ra hoàn toàn không thể đoán trước, đôi khi có 5 dòng được nhóm lại với nhau, nhóm 2 dòng, nhưng không có dòng 3.

Tôi đã nghĩ rằng có lẽ có vấn đề về dấu phân cách nên tôi đã thử chơi với tùy chọn -F và đặt IFS nhưng không thay đổi đầu ra.

Tôi nghĩ rằng tôi đang làm điều gì đó ngu ngốc theo cách tôi đã cố gắng kết hợp khớp mẫu với câu lệnh if nhưng tôi không thể tìm ra sự kết hợp.

Là những gì tôi đang cố gắng để làm có thể trong một lệnh awk duy nhất? Và nếu vậy, tôi sẽ đi sai ở đâu?

Câu trả lời:


7

Vấn đề với giải pháp đã cố gắng của bạn là awk NRlà số lượng các bản ghi đầu vào , trong khi bạn muốn chèn dòng mới dựa trên số lượng bản ghi đầu ra .

Tôi không nghĩ awk giữ số đếm như vậy, nhưng bạn có thể làm gì đó như

awk '/pattern1|pattern2|pattern3/ {print; if (++onr%3 == 0) print ""; }' infile

trong đó chúng tôi xác định một biến mới onr(cho số lượng bản ghi đầu ra - tên biến là tùy ý) và tăng nó mỗi khi chúng tôi khớp / in văn bản mong muốn, sau đó kiểm tra xem có chia hết cho 3 không và nếu vậy thì in một dòng mới.


Này @steel ấn. Những gì bạn đang nói hoàn toàn có ý nghĩa. Tôi đọc rằng NR là cho hồ sơ đầu vào. Nhưng tôi đã không tạo được mối liên hệ với cách tôi đang áp dụng logic. Tôi rõ ràng không có một sự hiểu biết đầy đủ. Giải pháp của bạn hoạt động! Có một điều kỳ lạ bây giờ; vì lý do nào đó hiện có 2 dòng trống giữa mỗi nhóm 3. Tôi sẽ xem liệu tôi có thể hiểu tại sao không. Xin lỗi vì sự thiếu hiểu biết của tôi, nhưng "++ onr%" làm gì chính xác? Tôi nghĩ rằng nó đang làm một số đếm, nhưng tôi không nhận ra onr. Cảm ơn bạn!
bourne

Hmmm Tôi đã thay đổi bản in thứ hai thành in "" và nó đã đi vào dòng trống bổ sung. Tôi nghĩ rằng tôi biết tại sao bây giờ. Đó là bởi vì trong infile có một đoạn dữ liệu, theo sau là một dòng trống, sau đó là một đoạn dữ liệu khác. Và với tuyên bố awk sạch hơn nhiều của bạn, dòng trống ban đầu đó sẽ không bị xóa.
bourne

Rất tiếc bạn đúng - dòng mới bổ sung là một lỗi trong mã của tôi ( printthêm một dòng mới theo mặc định). Như bạn đã lưu ý, nó có thể được sửa bằng cách thay đổi thành print ""- hoặc bạn có thể sử dụng printf "\n". Tôi sẽ chỉnh sửa câu trả lời.
Steeldo

cảm ơn bạn! Tôi thực sự đánh giá cao sự giúp đỡ của bạn. Vẫn còn nhiều điều để học hỏi.
bourne

0

Tôi có hiểu chính xác không, bạn đang cố gắng phát minh

awk '/pattern1|pattern2/ {print $1;} /pattern3/ {print $1 "\n"}' infile

Xin chào @ vasily-vm. Tôi không nghĩ rằng tôi đang cố gắng phát minh. Chủ yếu tôi đang cố gắng cải thiện mã awk của mình. Tôi cần 3 mẫu để được nhóm lại với nhau. Vấn đề là tôi sẽ kết thúc với nhiều nhóm 3. Sau mỗi nhóm 3 tôi cần đặt một dòng trống do một số hạn chế định dạng. Chúc mừng
bourne

xin lỗi, từ ngữ xấu :( trên thực tế, tôi đề xuất chia các mẫu thành 2 nhóm: nhóm thứ nhất sẽ sao chép nó, nhóm thứ hai - sẽ in thêm dòng mới sau khi in ví dụ chuỗi phù hợp của mẫu được cung cấp trong câu trả lời của tôi
vasily-vm
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.