Grep: conta o número de correspondências por linha

26

Estou tentando obter o número de correspondências (neste caso, ocorrências de {ou }) em cada linha de um arquivo .tex.

Eu sei que a -obandeira retorna apenas a correspondência, mas retorna cada correspondência em uma nova linha, mesmo combinada com a -nbandeira. Eu não sei de nada que eu possa passar para contar as repetições. O -csinalizador retorna apenas o número total de correspondências no arquivo inteiro - talvez eu possa canalizar uma linha de cada vez para grep?

Chris H
fonte

Respostas:

27
grep -o -n '[{}]' <filename> | cut -d : -f 1 | uniq -c

A saída será algo como:

3 1
1 2

Significado 3 ocorrências na primeira linha e 1 na segunda.

Retirado de /programming//a/15366097/3378354 .

Moebius
fonte
Obrigado - o Google encontrou muitos hits de regex no SU, mas não aquele no SO, que nem parece ter uma tag de regex. A sortnão é estritamente necessário como saída do grep é classificada pelo número da linha, mas eu acho que é uma boa prática antes uniq.
Chris H
2
Provavelmente não marcado regexporque o regex é a parte mais fácil.
Tom Zych
É realmente necessário sort -n? Ele não sai na ordem dos números de linha, afinal?
Tom Zych
Você está certo, sort -nnão é necessário. Obrigado.
Moebius
@ TomZych, descobriu-se que você estava certo, mas se eu soubesse que talvez não tivesse perguntado. O salto mental de grep para tag: regex talvez tenha sido um pouco demais.
Chris H
3

Depois de ler várias soluções, acho que essa é a abordagem mais fácil para o problema:

while read i; do echo $i |grep -o "matchingString"| wc -l;  done < input.txt
alfredocambera
fonte
3
Melhor solução, na minha opinião. Poderia ser ainda mais simplificada, reduzindo por um tubo: grep -o "matchingString" <<< $i | wc -l.
Benjamin W.
1
Este será ordens de magnitude mais lento, em seguida, outras opções embora
Rahul
1

Está usando grepum requisito? Aqui está uma alternativa:

sed / s / [^ {}] // g ' seu_arquivo | awk '{print NR, length}'

As sedtiras de todas as outras do que caracteres {e } (isto é, deixando apenas {e }caracteres), e, em seguida, as awkcontagens dos caracteres em cada linha (que são apenas os {e }caracteres). Para suprimir linhas sem correspondências,

sed / s / [^ {}] // g ' seu_arquivo | awk '/./ {print NR, length}'

Observe que minha solução assume (requer) que as strings que você está procurando são caracteres únicos. A resposta de Moebius é mais facilmente adaptada a cadeias de caracteres múltiplos. Além disso, nenhuma das nossas respostas exclui ocorrências citadas ou escapadas dos caracteres / sequências de interesse; por exemplo,

{ "nullfunc() {}" }

seria considerado como contendo quatro caracteres entre chaves.

Scott
fonte
grepnão era realmente um requisito, era justamente onde comecei a procurar uma solução, porque isso me proporcionou algo próximo. Eu nunca precisei do awk, por isso, se não tivesse usado a resposta acima, teria usado isso como uma chance de experimentar - ainda posso. O que não consegui esclarecer (mas isso não afeta nenhuma das respostas) é que eu queria executar o script uma vez por colchete, para me ajudar a rastrear uma incompatibilidade (na fonte LaTeX, aqui para uma tabela) em que a maioria dos pares ocorre. uma única linha.
Chris H
Não sei ao certo o que você quer dizer com "executar o script uma vez por colchete", mas se você deseja rastrear uma incompatibilidade entre chaves, tente algo como sed 's/{[^{}]*}//g' your_file | grep –n '[{}]', onde os sedpares de faixas (correspondentes). Se você tiver pares aninhados, use sed 's/{[^{}]*}//g;s/{[^{}]*}//g;s/{[^{}]*}//g;…' …, repetindo o s/{[^{}]*}//gnúmero de vezes que seu aninhamento mais profundo.
Scott
Eu quis dizer execute `sed 's / [^}] // g' your_file | awk '{imprime NR, comprimento}' e 's / [^ {] // g' seu_arquivo | awk '{print NR, length}'. Na verdade, tenho aninhamento, e trabalhar no nível mais profundo parecia uma tarefa árdua. Transformar muitas linhas em um punhado (existem alguns casos em que as chaves combinam apenas com várias linhas por razões válidas) funcionou bem (eu uso o jedit que destaca a chave correspondente - para qualquer tipo de chave que ela entende - então eu realmente fiz só preciso reduzi-lo).
Chris H