Đếm số dòng giữa


13

Tôi muốn đếm các dòng giữa "X" s. Đây chỉ là một ví dụ; Tôi phải áp dụng mã cho một kết quả sinh học phức tạp. Tôi sẽ rất biết ơn nếu bạn có thể đề xuất một số lệnh, tốt nhất là sử dụng awk, grephoặc sednhư tôi quen thuộc với những người.

Thí dụ:

X
Y
Y
Y
X
Y
Y
Y
Y
X
Y
X

Sản phẩm chất lượng:

3
4
1

2
Bạn có thể quan tâm đến Tin sinh học nếu bạn sẽ làm việc trong lĩnh vực này.
terdon

Câu trả lời:


13

Với awk:

$ awk '!/X/{count++}/X/{print count; count = 0}' input

3
4
1

Tăng một số lượng cho mỗi dòng không chứa X; in và thiết lập lại số đếm cho các dòng chứa X.


2
Nếu dòng đầu tiên không phải là một X, số dòng đầu tiên vẫn sẽ được tính và xuất ra với giải pháp này, cho đến khi dòng đầu tiên Xđược khớp. EX (Không thể thêm dòng mới vào nhận xét, nhưng hãy xem xét có một dòng mới giữa mỗi ký tự; P): Y X Y Y X Y Y Ysẽ xuất ra:1 2
Dan

1
@muru điều này sẽ không hoạt động nếu không có X ở cuối (cần thêm END{if (count)print count}) và tạo ra dòng trống trong đó X bắt đầu để tránh bạn cũng có thể thêm /X/&&countvào trong điều kiện
aғsнι

1
Heh. Một bình luận phàn nàn rằng Ykhông nên tính hàng đầu vì chúng không chính xác giữa hai Xs; người khác phàn nàn rằng dấu vết Ykhông được tính vì chúng không chính xác giữa hai Xgiây. Tôi sẽ đợi OP làm rõ, nếu cần; Tôi ổn với câu trả lời này cho đến khi đó.
muru

12
$ awk '/X/ && prev{print NR-prev-1} /X/{prev=NR}' file
3
4
1

Làm thế nào nó hoạt động:

Awk ngầm đọc qua các tệp đầu vào từng dòng.

  • /X/ && prev{print NR-prev-1}

    Đối với bất kỳ dòng nào có chứa Xvà nếu trước đây chúng ta đã gán một giá trị prev, sau đó in ra số dòng hiện tại NR, trừ prevđi một giá trị.

  • /X/{prev=NR}

    Đối với bất kỳ dòng nào có chứa X, đặt biến prevthành số dòng hiện tại , NR.


4
Hừ, đẹp quá. Lạm dụng NRcho tôi một ý tưởng:awk '/X/{print NR - 1; NR = 0}' foo
muru

Cảm ơn bạn, Nó cho tôi thông tin chính xác. đó là yêu cầu
Rhea

Muro: Đẹp & khéo léo. Ngoại trừ việc in một giá trị quá nhiều, nó hoạt động với tôi dưới gawk và mawk. Tôi tò mò liệu đây có phải là hành vi được đảm bảo hay không. @EdMorton?
John1024

3
@remat Trừ khi dòng đầu tiên của bạn luôn là một X, có một sự khác biệt nhỏ trong đầu ra giữa 2 câu trả lời như tôi đã giải thích trong một nhận xét dưới câu trả lời của muru.
Dan

1
@ John1024 cảm ơn bạn! Tôi hy vọng nó sẽ giúp tôi.
Rhea

6

Một awkcách tiếp cận đơn giản khác hoạt động trên dữ liệu mẫu của OP và nếu Xkhông có trong các X đầu tiên hoặc thậm chí lặp lại.

awk -v RS='X' 'NF{print NF}' infile

Trên đây là chính xác khi chỉ có một trường trong mỗi dòng với FS mặc định bất kỳ khoảng trắng nào , nếu không bên dưới được sửa đổi trong trường hợp chung để đếm theo dòng . Bạn có thể nhập MẪU của bạn thay cho X ở đó.

awk -F'\n' -v RS='X' 'NF>2{print NF-2}'

Đầu vào mẫu:

X
Y YYY Y
YY
YY Y YY YY Y Y
X
Y Y Y
X
Y
Y
X
X

Đầu ra là:

3
1
2

1

Hầu hết các câu trả lời ở đây khớp với nội dung của dòng được tính bằng các biểu thức thông thường được nhúng vào chương trình Awk. Nếu bạn cần khớp các dòng với nội dung có thể chứa các ký tự đặc biệt (với biểu thức Awk hoặc biểu thức chính quy), tốt hơn là thực sự so sánh các chuỗi cho đẳng thức. Do đó, tôi đề xuất kịch bản Awk sau đây như là một biến thể của câu trả lời của muru :

BEGIN {
    count = 0;
}

{
    if ($0 == needle) {
        if (count) {
            print count;
            count = 0;
        }
    } else {
        count++;
    }
}

Lưu trữ dưới dạng tệp văn bản, ví dụ: count-rows.awkvà gọi nó như sau:

awk -f count-rows.awk -v needle=X input

Bạn có thể điều chỉnh giá trị needletheo ý thích của bạn. Ưu điểm của phương pháp này là bạn có thể gọi chương trình từ tập lệnh shell với giá trị tùy ý needlemà không thoát khỏi các vấn đề:

awk -f count-rows.awk -v needle="$needle" input
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.