Como contar o número de caracteres em uma linha, exceto um caractere específico?

9

Este é um arquivo de peça

N W N N N N N N N N N
N C N N N N N N N N N
N A N N N N N N N N N
N N N N N N N N N N N
N G N N N N N N N N N
N C N N N C N N N N N
N C C N N N N N N N N

Em cada linha, quero contar o número total de todos os caracteres que não são "N"

meu desejo de saída

1
1
1
0
1
2
2
Anna1364
fonte
Use sedpara substituir coisas que você não se preocupam e awkpara contar o comprimento restantesed 's/N//g ; s/\s//g' file | awk '{ print length($0); }'
Rolf

Respostas:

13

Solução GNU awk :

awk -v FPAT='[^N[:space:]]' '{ print NF }' file
  • FPAT='[^N[:space:]]'- o padrão que define um valor de campo (qualquer caractere, exceto Nchar e espaço em branco)

A saída esperada:

1
1
1
0
1
2
2
RomanPerekhrest
fonte
9
awk '{ gsub("[ N]",""); print length() }'
Hauke ​​Laging
fonte
também pode usarawk '{print gsub(/[^ N]/,"")}'
Sundeep 7/07
7

assumindo que a contagem é necessária para cada linha que não seja o caractere de espaço e N

$ perl -lne 'print tr/N //c' ip.txt 
1
1
1
0
1
2
2
  • o valor de retorno tré quantos caracteres foram substituídos
  • c para complementar o conjunto de caracteres dados
  • Observe o uso da -lopção, retira o caractere de nova linha da linha de entrada para evitar erros de um por um e também adiciona caracteres de nova linha para a instrução print


Uma solução mais genérica

perl -lane 'print scalar grep {$_ ne "N"} @F' ip.txt 
  • -aopção para dividir automaticamente a linha de entrada em espaços em branco, salvos na @Fmatriz
  • grep {$_ ne "N"} @Fretorna a matriz de todos os elementos nos @Fquais não corresponde à stringN
    • equivalente regex seria grep {!/^N$/} @F
  • use of scalardará número de elementos da matriz
Sundeep
fonte
6

Solução alternativa do awk :

awk '{ print gsub(/[^N[:space:]]/,"") }' file
  • gsub(...)- A gsub()função retorna o número de substituições feitas.

A saída:

1
1
1
0
1
2
2
RomanPerekhrest
fonte
6

Outra awkabordagem (retornará -1 para linhas vazias).

awk -F'[^N ]' '$0=NF-1""' infile

Ou no complexo, ele retornará -1 nas linhas vazias, 0 nas linhas de espaços em branco (tabulações / espaços).

awk -F'[^N \t]+' '$0=NF-1""' infile
αғsнιη
fonte
imprimirá -1para linhas vazias ... mas, em seguida, que pode ser desejável para distinguir linha composta de apenas N / espaço vs linha vazia ...
Sundeep
1
@ Sundeep Sim, está correto. veja também minha atualização em que as linhas continham apenas guias ou espaços para indicar como 0
αғsнιη
5
  1. tre shell script POSIX :

    tr -d 'N ' < file | while read x ; do echo ${#x} ; done
    
  2. bash,, kshe zsh:

    while read x ; do x="${x//[ N]}" ; echo ${#x} ; done < file
    
agc
fonte
1
pode usar awk '{print length()}'para evitar o shell mais lento looping .. mas, em seguida, pode-se fazer tudo com a própria awk ...
Sundeep
@ Sundeep, é verdade ( se ambos são iniciados ao mesmo tempo), esse awkloop é mais rápido que o shell. Mas o shell está sempre na memória e awkpode não estar - quando awkainda não está carregado ou trocado, a sobrecarga de carregá-lo ( o tempo perdido ) pode ser maior que a vantagem de executar awk- principalmente em um pequeno ciclo. Nesses casos, ( ou seja, neste caso), awkpode ser mais lento .
AGC
bem, certamente não estou preocupado com o tempo para coisas pequenas ... consulte unix.stackexchange.com/questions/169716/…
Sundeep 7/17
1
@Sundeep, eu faço preocupação. Algum tempo atrás, eu costumava usar distribuições Linux baseadas em disquete , que podiam ser executadas em um disquete, em alguns megas de memória RAM. Usar desnecessariamente awkum script de shell pode fazer com que esse sistema se arraste de quatro. Geralmente: o mesmo arrasto de latência se aplica a sistemas com firmware limitado ou a qualquer sistema com carga pesada.
AGC
1

Uma pequena combinação de tre awk:

$ tr -d ' N' <file.in | awk '{ print length }'
1
1
1
0
1
2
2

Isso exclui todos os espaços e Ns do arquivo de entrada e awkapenas imprime o comprimento de cada linha.

Kusalananda
fonte
0

Outra maneira fácil é fazê-lo em python, que vem pré-instalado na maioria dos ambientes unix. Solte o seguinte código em um arquivo .py:

with open('geno') as f:
    for line in f:
        count = 0
        for word in line.split():
            if word != 'N':
                count += 1
        print(count)

E então faça:

python file.py

Do seu terminal. O que o acima faz é:

  • para cada linha em um arquivo chamado "geno"
  • defina um contador para 0 e aumente cada vez que encontrarmos um valor! = 'N'
  • quando chegar ao fim da linha atual, imprima o contador e vá para a próxima linha
Grajdeanu Alex.
fonte