Как посчитать вхождение шаблона в линию

8

У меня есть файл, который имеет три столбца. Столбец 3 содержит названия генов, и это выглядит так:

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

Как я могу напечатать количество генов в каждом ряду?

Saisha
источник
Четвертый столбец? Что должно произойти, если этот столбец уже занят (вторая строка в вашем примере), или если другие столбцы пусты (последняя строка)?
Кусалананда
@Kusalananda Убрал этот критерий из моего запроса :)
Saisha
Вкратце, все ответы подсчитывают поля или строки, разделенные запятыми, соответствующие Rv*шаблону в любом месте строки, а не только в определенном столбце. Поэтому я просто отмечу, что если у вас на самом деле есть другие данные в файле, не представленные в этом вопросе, возможно, вам придется соответствующим образом изменить решения. (Или
уточните

Ответы:

10

Вы просто хотите добавить столбец с количеством столбцов в нем. Это может быть сделано с помощью awk:

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

NFэто awkпеременная , содержащая количество полей (столбцов) в текущей записи (строки). Мы печатаем это число, за которым следуют запятая и остальная часть строки для каждой строки.

Альтернатива (тот же результат, но может выглядеть немного чище):

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

FSэто разделитель полей, который awkиспользуется для разделения каждой записи на поля, и мы устанавливаем это в запятую -F ','в командной строке (как в первом решении). OFSявляется разделителем выходного поля, и мы устанавливаем его таким же, как и FSдо чтения первой строки ввода.

Кусалананда
источник
5

Если вы хотите посчитать количество вхождений Rv[0-9]{4}c?шаблона, а не количество полей, разделенных запятыми, как предполагает тема вашего вопроса, вы можете сделать следующее:

 awk '{print gsub(/Rv[0-9]{4}c?/, "&"), $0}'
Стефан Шазелас
источник
4

Подход Perl:

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

В -aмарке perlведет себя , как awkи разделить каждую строку ввода на строке , заданной -Fи сохранение полученных полей в массив @F. Следовательно, $#Fбудет самый высокий индекс массива @Fи, поскольку массивы начинают отсчитываться с 0, $#F+1будет общим количеством элементов в массиве. В -pозначает «печать каждую строку ввода после того, как aplpying сценарий , данное -e. s///Оператор замещения и здесь были заменяют начало линии ( ^) с количеством полей + 1 и запятой ( $#F+1 . ",").

Тердон
источник
1

Ваш вопрос утверждает, что столбец 3 содержит названия генов. Я предполагаю, что ваш фактический вклад выглядит следующим образом:

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

Каждое имя гена в column3 содержит ведущую Rvподстроку. Таким образом, мы можем считать их в Python так:

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

Результирующий список показывает количество генов в каждой строке в соответствующем порядке. Если мы хотим сделать его более подробным и включить возможность того, что гены могут не содержать строку «Rv» (но придерживаться предположения, что column3 - это строка значений, разделенных запятыми), мы также можем сделать следующее:

#!/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))

Тестовый забег:

$ ./count_genes.py input.txt                                                                                             
Line 0 contains 3
Line 1 contains 4
Line 2 contains 1
Сергей Колодяжный
источник