Làm thế nào để đếm sự xuất hiện của một mẫu trong một dòng


8

Tôi có một tập tin có ba cột. Cột 3 chứa tên của các gen và nó trông như thế này:

Rv0729,Rv0993,Rv1408  
Rv0162c,Rv0761c,Rv1862,Rv3086  
Rv2790c

Làm thế nào tôi có thể in số lượng gen trong mỗi hàng?


Một cột thứ tư? Điều gì sẽ xảy ra nếu cột đó đã bị chiếm dụng (hàng thứ hai trong ví dụ của bạn) hoặc nếu các cột khác trống (hàng cuối cùng)?
Kusalananda

@Kusalananda Đã xóa tiêu chí đó khỏi truy vấn của tôi :)
Saisha

Nhìn nhanh, tất cả các câu trả lời đều đếm các trường hoặc chuỗi được phân tách bằng dấu phẩy khớp với Rv*mẫu ở bất kỳ đâu trên dòng không chỉ trong một cột cụ thể. Vì vậy, tôi sẽ chỉ lưu ý rằng nếu bạn thực sự có dữ liệu khác trong tệp, không được trình bày trong câu hỏi ở đây, bạn có thể cần phải sửa đổi các giải pháp cho phù hợp. (Hoặc làm rõ câu hỏi.)
ilkkachu

Câu trả lời:


10

Bạn chỉ muốn thêm một cột với số lượng cột trong đó. Điều này có thể được thực hiện bằng cách sử dụng awk:

$ awk -F ',' '{ printf("%d,%s\n", NF, $0) }' data.in
3,Rv0729,Rv0993,Rv1408
4,Rv0162c,Rv0761c,Rv1862,Rv3086
1,Rv2790c

NFlà một awkbiến chứa số lượng trường (cột) trong bản ghi hiện tại (hàng). Chúng tôi in số này theo sau là dấu phẩy và phần còn lại của hàng cho mỗi hàng.

Một thay thế (kết quả tương tự, nhưng có thể trông sạch hơn một chút):

$ awk -F ',' 'BEGIN { OFS=FS } { print NF, $0 }' data.in

FSlà dấu tách trường awksử dụng để phân tách từng bản ghi thành các trường và chúng tôi đặt dấu phẩy thành dấu phẩy -F ','trên dòng lệnh (như trong giải pháp đầu tiên). OFSlà dấu phân cách trường đầu ra và chúng tôi đặt nó giống như FStrước khi đọc dòng đầu tiên đầu tiên.


5

Nếu bạn muốn đếm số lần xuất hiện của Rv[0-9]{4}c?mẫu trái ngược với số trường được phân cách bằng dấu phẩy như chủ đề của câu hỏi của bạn, bạn có thể làm:

 awk '{print gsub(/Rv[0-9]{4}c?/, "&"), $0}'

4

Một cách tiếp cận Perl:

$ perl -F, -pae 's/^/$#F+1 . ","/e' file
3,Rv0729,Rv0993,Rv1408  
4,Rv0162c,Rv0761c,Rv1862,Rv3086  
1,Rv2790c

Việc -athực hiện perlhành vi như awkvà phân chia từng dòng đầu vào trên chuỗi được cung cấp bởi -Fvà lưu các trường kết quả vào mảng @F. Do đó, $#Fsẽ là chỉ số mảng cao nhất trong @Fvà, vì các mảng bắt đầu đếm tại 0, $#F+1sẽ là tổng số phần tử trong mảng. Có -pnghĩa là "in mọi dòng đầu vào sau khi áp dụng tập lệnh được đưa ra bởi -e. s///Toán tử thay thế và ở đây đang thay thế phần đầu của dòng ( ^) bằng số trường + 1 và dấu phẩy ( $#F+1 . ",").


1

Câu hỏi của bạn nói rằng cột 3 chứa tên của các gen. Tôi giả sử đầu vào thực tế của bạn là như sau:

column1 column2 Rv0729,Rv0993,Rv1408  
column1 column2 Rv0162c,Rv0761c,Rv1862,Rv3086  
column1 column2 Rv2790c

Mỗi tên gen trong cột 3 chứa Rvchuỗi con hàng đầu . Vì vậy, chúng ta có thể đếm chúng trong python như vậy:

$ python -c  "import sys;print map(lambda x: x.split()[2].count('Rv'),sys.stdin.readlines())"  < input.txt               
[3, 4, 1]

Danh sách kết quả cho thấy số lượng gen trong mỗi dòng, theo thứ tự tương ứng của chúng. Nếu chúng ta muốn làm cho nó dài dòng hơn và bao gồm khả năng các gen có thể không chứa chuỗi "Rv" (nhưng vẫn giữ giả định rằng cột 3 là chuỗi giá trị được phân tách bằng dấu phẩy), chúng ta cũng có thể làm như sau:

#!/usr/bin/env python
import sys
with open(sys.argv[1]) as fd:
    for index,line in enumerate(fd):
        columns = line.strip().split()
        num_genes=len(columns[2].split(","))
        print("Line "+str(index)+" contains "+str(num_genes))

Chạy thử nghiệm:

$ ./count_genes.py input.txt                                                                                             
Line 0 contains 3
Line 1 contains 4
Line 2 contains 1
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.