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"

minha saída de desejo

1
1
1
0
1
2
2
    
por Anna1364 06.10.2017 / 22:39

8 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 N char e espaço em branco)

A saída esperada:

1
1
1
0
1
2
2
    
por 06.10.2017 / 22:45
9
awk '{ gsub("[ N]",""); print length() }'
    
por 06.10.2017 / 22:48
7

assumindo que a contagem é necessária para cada linha diferente do caractere de espaço e N

$ perl -lne 'print tr/N //c' ip.txt 
1
1
1
0
1
2
2
  • valor de retorno de tr é quantos caracteres foram substituídos
  • c para complementar o conjunto de caracteres fornecidos
  • Observe o uso da opção -l , elimina o caractere de nova linha da linha de entrada para evitar erros "off-by-one" e também adiciona caracteres de nova linha para a declaração de impressão


Uma solução mais genérica

perl -lane 'print scalar grep {$_ ne "N"} @F' ip.txt 
  • -a opção para dividir automaticamente a linha de entrada em espaços em branco, salvos em @F array
  • grep {$_ ne "N"} @F retorna array de todos os elementos em @F que não corresponde à string N
    • o equivalente regex seria grep {!/^N$/} @F
  • o uso de scalar fornecerá o número de elementos da matriz
por 07.10.2017 / 06:52
6

Solução alternativa awk :

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

A saída:

1
1
1
0
1
2
2
    
por 06.10.2017 / 23:05
6

Outra abordagem awk (retornará -1 para linhas vazias).

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

Ou no complexo, ele retornará -1 em linhas vazias, 0 somente em linhas de espaços em branco (Tabs / Spaces).

awk -F'[^N \t]+' '$0=NF-1""' infile
    
por 06.10.2017 / 23:30
5
  1. Script de shell

    tr e POSIX :

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

    while read x ; do x="${x//[ N]}" ; echo ${#x} ; done < file
    
por 07.10.2017 / 04:19
1

Uma combinação curta de tr e awk :

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

Isso exclui todos os espaços de um Ns do arquivo de entrada e awk apenas exibe o tamanho de cada linha.

    
por 08.10.2017 / 10:30
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 isso faz é:

  • para cada linha em um arquivo chamado "geno"
  • definir um contador como 0 e incrementá-lo sempre que encontrarmos um valor! = 'N'
  • quando o fim da linha atual for alcançado, imprima o contador e vá para a próxima linha
por 07.10.2017 / 13:15