BASH: conta o número de palavras em cada linha de um documento

3

Eu preciso identificar padrões em um arquivo de texto para análise posterior. Portanto, os arquivos de entrada podem conter texto semiestruturado da seguinte forma:

file1

905:john: abc123: [email protected]: US  
920:eric: ericaA: [email protected]: US  
1000: rio: ri0ri0: [email protected]: IN  

file2

nathen <tab> [email protected] <tab> 764323545 <tab> UK
thomas <tab> [email protected] <tab> 563363421 <tab> UK
ian <tab> [email protected] <tab> 3453245472 <tab> SP

O número de palavras em uma linha pode variar para cada documento. o delimitador também varia, mas é único para cada documento. o que eu quero é contar o número de palavras por cada linha em cada documento.

saída seria:

para arquivo1

5  
5 
5 
5   

para o arquivo2

4  
4 
4 
4

Eu quero generalizar isso para qualquer arquivo com qualquer delimitador. Pode ser - | : \space+ \tab+ .

Alguns arquivos são os seguintes:

| [email protected] | er34532 |  
| [email protected] | 764474 |
    
por user3148655 15.05.2016 / 05:23

2 respostas

6

Para o arquivo 2 com seu formato simples de palavras separadas por espaços em branco, tente:

$ awk '{print NF}' file2
4
4
4

No awk, NF é o número de campos. No awk por padrão, os caracteres das palavras são separados por espaços em branco.

Para o arquivo1, para o qual as palavras podem ser separadas por dois pontos ou espaços, precisamos adicionar : ao separador de campos:

$ awk -F'[: \t]+' '{print NF}' file1
5
5
5

Melhoria

o awk vai achar que existem campos extras se uma linha tiver espaços em branco à esquerda ou à direita. Podemos consertar isso removendo qualquer espaço em branco antes de contarmos os campos, assim para o arquivo1:

awk -F'[: \t]+' '{gsub(/^[: \t]+|[: \t]+$/, ""); print NF}' file1

ou isto para o arquivo2:

awk '{gsub(/^[[:space:]]+|[[:space:]]+$/, ""); print NF}' file2

Na regex, ^[[:space:]]+ corresponde ao espaço em branco inicial e [[:space:]]+$ corresponde a espaços em branco finais. A combinação deles no comando gsub remove os dois.

Generalização

Se o separador de campo puder ser qualquer um dos | : ou então, use:

awk -F'[-|: \t]+' '{gsub(/^[[-\|: \t]+|[[-\|: \t]+$/, ""); print NF}'

Exemplo:

$ cat file3
| [email protected] | er34532 |  
| [email protected] | 764474 |
$ awk -F'[-|: \t]+' '{gsub(/^[[-\|: \t]+|[[-\|: \t]+$/, ""); print NF}' file3
2
2
    
por 15.05.2016 / 05:51
2

Você pode usar este truque em perl para contar substrings correspondentes a uma palavra regex de sua escolha, por exemplo para contar sequências de "palavras" que consistem no conjunto de caracteres \w do perl aumentadas com @ e .

perl -lne 'print my $count = () = $_ =~ /[\w@.]+/g' somefile

que dá

$ perl -lne 'print my $count = () = $_ =~ /[\w@.]+/g' file1
5
5
5

e

$ perl -lne 'print my $count = () = $_ =~ /[\w@.]+/g' file2
4
4
4

para seus arquivos de amostra.

    
por 15.05.2016 / 14:16

Tags