Como contar a ocorrência de uma string específica em uma linha específica de um arquivo?

6

Eu sei que posso usar o wc para retornar o número total de palavras (e linhas) em um arquivo usando:

wc <filename>

Existe uma maneira de retornar a contagem de uma string específica em uma linha específica de um arquivo?

Algo como o seguinte:

wc -<flag> <line number> -<flag> <string> <filename>
    
por Donald Peat 29.06.2017 / 23:06

5 respostas

9

Isso precisa ser feito em três etapas:

  1. Selecione o número da linha N (o exemplo usa a linha 42):

    sed '42!d'
    
  2. Pesquise na linha todas as ocorrências de um padrão específico (aqui a string / expressão regular hello ) e imprima as separadamente:

    grep -o 'hello'
    
  3. Conte as correspondências:

    wc -l
    

Ou para colocá-lo em um único pipe de comando, lendo file.txt :

sed '42!d' file.txt | grep -o 'hello' | wc -l
    
por Byte Commander 29.06.2017 / 23:19
8

Este é um bom caso de uso para unir as ferramentas do Unix em um pipeline.

line=5
str="ipsum"
sed -n "${line}p" filename | grep -o -- "$str" | wc -l

O comando sed p produz a linha dada do arquivo e a alimenta no grep. A opção -o do Grep diz para a saída de todas as correspondências para a string dada, e cada correspondência é enviada em uma linha separada. A saída de Grep é alimentada para wc, que conta o número de linhas.

    
por Mark Plotnick 29.06.2017 / 23:20
7

Python

Aqui está uma maneira de fazer isso em Python através da compreensão da lista (veja abaixo para uma versão alternativa mais curta).

$ python -c 'import sys;print([ l for i,l in enumerate(sys.stdin,1) if i==2][0].count("word"))' < input.txt                                          
3
$ cat input.txt
nothing here
word and another word, and one more word
last line

Como isso funciona:

  • nós executamos o interpretador python com -c flag, os comandos estão contidos entre aspas simples;
  • o arquivo de entrada input.txt é redirecionado para stdin stream do interpretador python via < shell operator. Por isso, precisamos de sys module.
  • Usando a estrutura de compreensão de listas [something for item in something] , lemos linhas de texto de sys.stdin .
  • enumerate(sys.stdin,1) nos permite enumerar as linhas, ou seja, a cada iteração da compreensão da lista, obteremos a linha de texto na variável l e indexaremos na variável i iniciando a contagem em 1.
  • O i==2 filtrará apenas a linha cujo índice é igual a 2. É assim que sabemos qual linha extrair.
  • Assim, como resultado, nossa lista conterá apenas um item e, dentro da lista, seu índice será 0 . Então, nos referimos a esse item como [<list comprehension stuff here>][0] . -O .count("word") é o que realmente faz o trabalho de contar. Por definição, ele retorna um número de ocorrências não sobrepostas de uma substring em uma string.
  • finalmente, tudo isso estava contido na declaração print() . Então, qualquer número que o método .count() retorne aparecerá na tela.

Versão mais curta

A maneira mais curta de fazer o mesmo em Python seria usar o método readlines() em vez da compreensão da lista e referir-se ao item específico na lista que readlines() produz. Note que readlines() produz uma lista, e listas em Python são indexadas em 0, o que significa que se você quiser ler a linha x, você deve referenciar o item de lista x-1. Por exemplo,

$ python -c 'import sys;print(sys.stdin.readlines()[1].count("word"))' < input.txt       
3

sed + grep

É claro que não precisamos nos limitar apenas às linguagens de script. sed e grep fornecem ferramentas suficientes que podemos usar para atender às nossas necessidades. Com grep -c podemos contar a ocorrência de linhas correspondentes, então tudo o que precisamos fazer é extrair a linha específica que precisamos e dividir todas as palavras dessa linha em linhas separadas. Assim:

$ sed -n  '2{s/ /\n/g;p}' input.txt | grep -c 'word'
3
    
por Sergiy Kolodyazhnyy 30.06.2017 / 00:00
6

awk solution:

awk 'NR==X { print gsub("word",""); }' file
  • altere o X com seu número de linha específico.
  • altere a "palavra" com a palavra desejada.
  • gsub retorna o número de substituição da "palavra", parece que estamos contando isso.

Exampe:

$ cat file:
a b c a a d
d e f f f 1

vamos ver quantos 'f' chegamos na linha "2":

$ awk 'NR==2 { print gsub("f",""); }' file
3
    
por Ravexina 29.06.2017 / 23:28
5

Uma maneira de fazer isso, em perl :

perl -lne '
  BEGIN{($lineno, $str) = splice @ARGV,0,2} 
  print $c = () = /$str/g if $. == $lineno
' <lineno> <string> <filename>
    
por steeldriver 29.06.2017 / 23:19