Греп, который работает с перекрывающимися узорами

Я хочу подсчитать количество повторяющихся паттернов aa в очень большом файле. Поэтому я использую следующую команду:

 grep -o "aa" ./bwt/dblp.txt | wc -l 

Это работает, за исключением случаев, когда у меня есть строка, такая как aaa , которая затем соответствует этому как только 1 шаблон. В моем случае использования мне нужно, чтобы первые 2 a s означали один шаблон, но последние 2 a s являются вторым patter (это означает, что середина a из aaa может быть повторно использована).

Как я могу это достичь?

Обратите внимание, что файл очень большой, поэтому «оптимизированный» способ, если возможно, будет лучше. Во всяком случае, любое рабочее решение, безусловно, приветствуется.

Для этого вам нужны регулярные выражения perl. С grep который поддерживает флаг -P :

 grep -oP '(?<=a)a' file | wc -l 

Это позитивный взгляд . Он соответствует одному a которому предшествует другое a .


Если вы предпочитаете perl (или ваш grep не поддерживает флаг -P ):

 perl -ne 'while(m/(?<=a)a/g){$a++}END{print "$a\n"}' file 

Пример:

 $ cat file aa aaa aaaa 

Первая строка должна быть 1, вторая и вторая; все вместе 6:

 $ grep -oP '(?<=a)a' file | wc -l 6 

Вы можете подсчитать повторяющиеся пары букв, например, ваш пример aa в файле данных big_file например:

 tr -cs a '\012' <big_file | awk '/aa/{n += length - 1}; END {print n+0}' 

Строку можно объяснить так:

  • tr изменяет любую последовательность символов, которая не является символом новой строки. Это разделяет несколько вхождений aa... на отдельные строки
  • awk подсчитывает длину ненулевых линий. Используя свойство, что последовательность из N символов содержит N-1 перекрывающиеся пары, он может суммировать количество перекрывающихся пар и произвести общее количество в конце файла

Фактически, поскольку файл «очень большой», вы получите лучший ответ, включив grep в конвейер следующим образом:

 tr -cs a '\012' <big_file | grep aa | awk '{n += length - 1}; END {print n+0}' 
 grep -ow aa ./bwt/dblp.txt | wc -l