Como obter a contagem única de uma parte específica de uma string

2

Eu tenho um conjunto de dados em um arquivo.

psf7433-nlhrms
unit7433-nobody
unit7333-opera
bpx7333-operations
app7333-osm
unit7330-partners
psf7331-pdesmond
unit7333-projm
mnp7330-redirect
unit7333-retailbanking
cpq7333-rkarmer
unit6333-sales
ring7323-support
unit7133-telco
post7323-uadb
sun7335-ukhrms
burp7133-wfnmreply

Como ignorar os caracteres alfabéticos iniciais em cada linha e os caracteres após o numérico e obter a contagem dos números exclusivos. (ou) Como recuperar apenas o valor numérico em cada linha e obter sua contagem exclusiva.

Considerando que conseguimos extrair apenas os valores numéricos, obteremos isso.

7433
7433
7333
7333
7333
7330
7331
7333
7330
7333
7333
6333
7323
7133
7323
7335
7133

Agora, desejo a contagem exclusiva dos valores numéricos recuperados. Então, ignorando as repetições, eu deveria obter a seguinte saída final.

8

Eu não consigo fazer isso usando awk ou sed ou até mesmo simples grep | cortar

Eu não quero a lista de valores extraídos, quero apenas a contagem final como resposta.

Me ajude!

    
por Karthik 09.12.2014 / 16:01

5 respostas

5

Com grep , filtre apenas os números:

grep -Eo '[0-9]+-' file | sort -u | wc -l
  • [0-9] Corresponde a qualquer caracter entre 0 e 9 (qualquer dígito).
  • + em expressões regulares estendidas significa pelo menos um caractere (é por isso que a opção -E é usada com grep ). Portanto, [0-9]+- corresponde a um ou mais dígitos, seguido por - .
  • -o imprime apenas a parte que correspondeu ao seu padrão, então, dada a entrada abcd23-gf56 , grep somente imprimirá 23- .
  • sort -u classifica e filtra entradas exclusivas (devido a -u ) e wc -l conta o número de linhas na entrada (portanto, o número de entradas exclusivas).
por 09.12.2014 / 16:07
1

Você pode usar:

tr -dc '\-0-9\n' | sort -u -t- -nk1,1 | grep -c .

... que é, reconhecidamente, mais do que um pouco inspirado pela resposta de muru aqui. Diferentemente, porém, eu uso grep para contar as linhas em vez de wc no caso de haver linhas em branco na entrada. Sua resposta não tem um problema de linha em branco, pois grep -o só imprimirá linhas com sua correspondência (como grep -c só as conta aqui) , mas tr faz imprima linhas em branco porque a nova linha é um dos poucos caracteres que ela não exclui. Isso significa que qualquer número de linhas em branco na entrada distorceria os resultados de wc em um.

Portanto, tr é mais eficiente do que é grep -o , mas provavelmente wc bate grep no departamento de contagem. Eu gosto desse jeito, penso, por razões de portabilidade, e também porque eu costumo tentar remover os dados com o filtro mais eficiente primeiro, e usar os menos eficientes posteriormente na cadeia.

Isso permite que sort escolha os bits por linha que serão considerados em sua -u nique sort baseada em sua -n umeric sort -k ey que é dividida em seu delimitador -t- ab. tr -d elimina o -c omplement de qualquer byte numérico, traço ou nova linha em sua entrada. Dessa forma - desde que não haja - traços ocorrendo antes das cadeias numéricas que você deseja comparar, então a única coisa que resta em qualquer linha é:

#nothing at all

... ou ...

[numbers]

... ou ...

[numbers]-[more numbers]more-dashes-...

Assim, quando a saída é canalizada para sort , instruímos apenas para comparar cadeias numéricas que ocorrem antes de um traço, se houver. Demos ou não - os únicos números que importam são os que você quer contar.

Então, nós grep -c ount linhas contendo pelo menos um único caractere . . O comando a seguir imprime 8 :

tr -dc '\-0-9\n' <<\IN | sort -u -t- -nk1,1 | grep -c .
psf7433-nlhrms
unit7433-nobody
unit7333-opera
bpx7333-operations
app7333-osm
unit7330-partners
psf7331-pdesmond
unit7333-pro-09-0jm
mnp7330-redir09o-0ect
unit7333-retailbanking
cpq7333-rkarmer
unit6333-sales
ring7323-support


unit7133-telco
post7323-uadb
sun7335-ukhrms
burp7133-wfnmreply
IN
    
por 10.12.2014 / 01:59
1

Use grep estendido para e procure por quatro dígitos, dizendo ao grep para listar apenas as correspondências (ao contrário da linha inteira, que é o padrão):

grep -Eo '[0-9]+' <filename>

Classifique esta lista de números e apenas produza os únicos:

sort -u

Conte o número de linhas:

wc -l

Coloque tudo junto:

$ grep -Eo '[0-9]+' filename | sort -u | wc -l
8
    
por 09.12.2014 / 16:14
0

Com , sem canos de shell (mais rápido):

$ perl -lne '/\d+-/ and $h{$&}++;END{print scalar keys %h}' file
    
por 09.12.2014 / 16:06
0

Uma solução awk

awk -F'-' '{sub(/[^[:digit:]]+/, "", $1); a[$1]} END{for (k in a) ++i; print i}' file
8
    
por 09.12.2014 / 16:29