2012-07-19 6 views
10

Tôi muốn in các dòng lẻ (1,3,5,7 ..) mà không có bất kỳ thay đổi nào, nhưng ngay cả dòng (2,4,6,8) quá trình với đường ống bắt đầu bằng grep. Tôi muốn viết tất cả mọi thứ vào tệp mới (các dòng lẻ mà không có bất kỳ thay đổi nào và các giá trị mới cho các dòng chẵn).Làm thế nào để xử lý tất cả các dòng khác trong bash

Tôi biết làm thế nào để in tất cả các dòng khác trong awk:

awk ' NR % 2 == 1 { print; } NR % 2 ==0 {print; }' file.fasta 

Tuy nhiên, cho dù dòng, Tôi không muốn sử dụng {print; } nhưng tôi muốn sử dụng đường ống dẫn grep của tôi để thay thế.

Lời khuyên sẽ được đánh giá cao. Cảm ơn rất nhiều.

+3

'== 1 {print;}' là dự phòng, chỉ cần 'awk' NR% 2 'sẽ in các dòng lẻ' – Kevin

+0

cảm ơn tất cả vì sự trợ giúp! – Perlnika

Trả lời

8

Nếu bạn đang lập kế hoạch để làm một đơn giản grep, bạn có thể loại bỏ các bước bổ sung và làm các việc lọc trong bản thân awk, ví dụ:

awk 'NR % 2 {print} !(NR % 2) && /pattern/ {print}' file.fasta 

Tuy nhiên, nếu bạn có ý định làm nhiều hơn sau đó, như chepner already pointer out, bạn có thể thực sự ống từ bên awk . Ví dụ:

awk 'NR % 2 {print} !(NR % 2) {print | "grep pattern | rev" }' file.fasta 

Điều đó sẽ mở một đường ống đến lệnh "pattern | rev" (lưu ý các dấu ngoặc kép xung quanh) và chuyển hướng đầu ra in tới nó. Lưu ý rằng đầu ra trong trường hợp này có thể không như bạn mong đợi; bạn sẽ kết thúc với tất cả các dòng lẻ được sản xuất đầu tiên theo sau là đầu ra của lệnh đường ống (mà tiêu thụ các dòng thậm chí).


(Để đối phó với ý kiến ​​của bạn) để đếm số ký tự trong mỗi dòng thậm chí, hãy thử:

awk 'NR % 2 {print} !(NR % 2) {print length($0)}' file.fasta 
+0

Cảm ơn. Tôi sắp đếm số chữ cái trong cả hai dòng. – Perlnika

+0

@Perlnika bạn có thể nhận được số lượng ký tự bằng cách sử dụng lệnh 'length' trong awk. Xem câu trả lời được cập nhật. –

+0

@Perlnika, một số tệp fasta có thể chứa các ký tự trống như '-' hoặc' X', nhưng bạn có thể đã trả lời những gì OP muốn. – Steve

6

Bạn có thể đường ống trực tiếp từ bên trong awk:

awk ' NR % 2 == 1 { print; } NR % 2 ==0 {print | "grep -o [actgnACTGN] | wc -l"; }' file.fasta 

Hãy nhận biết, tuy nhiên, điều này sẽ không duy trì trật tự của tập tin đầu vào của bạn.

(Câu trả lời được lựa chọn là tốt hơn cho nhiệm vụ trong tầm tay, nhưng tôi sẽ để lại câu trả lời này ở đây như là một ví dụ về đường ống lệnh in đến một lệnh bên ngoài.)

+0

Cảm ơn, tôi đã thử điều này với awk 'NR% 2 == 1 {print; } NR% 2 == 0 {in | grep -o [actgnACTGN] | Tệp wc -l} '.fasta (để đếm số chữ cái trong dòng) nhưng có vấn đề với wc nói: awk: dòng 1: lỗi cú pháp tại hoặc gần wc (để tôi đoán vấn đề nằm trong đường dẫn của tôi :) – Perlnika

+0

Ý của bạn là gì không giữ gìn trật tự? – Perlnika

+0

@Perlnika Ông có nghĩa là bạn sẽ kết thúc với tất cả các dòng lẻ được sản xuất đầu tiên theo sau là đầu ra của đường ống (mà tiêu thụ tất cả các dòng ngay cả) –

1

Để có sản lượng đường ống của bạn xuất hiện theo thứ tự với sản lượng AWK, bạn cần phải đóng đường ống tại mỗi lần lặp lại. Đây là, tất nhiên, rất kém hiệu quả.

awk 'BEGIN{ cmd = "grep -io \047[actgn]\047 | wc -l" } NR % 2 { print } NR % 2 == 0 { print | cmd; close(cmd) }' file.fasta 

Bạn dường như không muốn tính các ký tự không có trong danh sách được chỉ định, vì vậy length($0) sẽ không hoạt động. Điều này sẽ làm việc và nên nhanh hơn rất nhiều so với phương pháp đường ống:

awk 'NR % 2 { print } NR % 2 == 0 {n = split($0, a, /[^actgnACTGN]/); print length($0) - n + 1}' file.fasta 

Nó hoạt động bằng cách phân chia các dòng sử dụng các ký tự bạn không muốn như delimiters và trừ đi số của chuỗi con từ chiều dài của dòng và thêm 1. Về bản chất, nó trừ số ký tự không mong muốn từ độ dài của dòng để lại số ký tự mong muốn như là kết quả.