AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / unix / Perguntas / 468966
Accepted
phg
phg
Asked: 2018-09-14 23:26:39 +0800 CST2018-09-14 23:26:39 +0800 CST 2018-09-14 23:26:39 +0800 CST

Contar linhas com mais de 80 colunas, levando em consideração as guias corretamente

  • 772

Para contar linhas com mais de 80 colunas estou, atualmente, usando este comando:

$ git grep -h -c -v '^.\{,80\}$' **/*.{c,h,p{l,y}} \
    |awk 'BEGIN { i=0 } { i+=$1 } END { printf ("%d\n", i) }'
44984

Infelizmente, o repositório usa guias para recuar, portanto, o greppadrão é impreciso. Existe alguma maneira de ter as regexguias de tratamento na largura padrão de 8 caracteres, como wc -Lacontece?

Para os propósitos desta pergunta, podemos supor que os colaboradores foram disciplinados o suficiente para recuar consistentemente, ou que eles têm git commitganchos em vez de disciplina.

Por motivos relacionados ao desempenho, prefiro uma solução que funcione dentro git-grep(1)ou talvez outra grepferramenta, sem pré-processamento de arquivos .

grep
  • 4 4 respostas
  • 1339 Views

4 respostas

  • Voted
  1. Kusalananda
    2018-09-14T23:50:39+08:002018-09-14T23:50:39+08:00

    Pré-processe os arquivos canalizando-os através de expand. O expandutilitário expandirá as guias adequadamente (usando as paradas de tabulação padrão a cada 8 caracteres).

    find . -type f \( -name '*.[ch]' -o -name '*.p[ly]' \) -exec expand {} + |
    awk 'length > 80 { n++ } END { print n }'
    
    • 12
  2. Stéphane Chazelas
    2018-09-14T23:48:25+08:002018-09-14T23:48:25+08:00

    GNU wc -Lnão trata TABs como 8 caracteres, ele trata TABs como eles seriam exibidos em um terminal com paradas de TAB a cada 8 colunas, então teria uma "largura" variando de 1 a 8 caracteres, dependendo de onde eles são encontrados na linha . wc -Ltambém considera a largura de exibição de outros caracteres (se eles têm 0, 1 ou 2 colunas de largura) e também processa \fe \r"corretamente".

    $ printf 'abcde\t\n' | wc -L
    8
    

    Aqui, você pode usar expand(que por padrão também assume paradas de tabulação a cada 8 colunas, embora você possa alterá-lo com opções) para expandir essas TABs para espaços:

    git grep -h '' ./**/*.{c,h,p{l,y}} | expand | tr '\f\r' '\n\n' | grep -cE '.{81}'
    

    (convertendo os CRs (que quando enviados para um terminal movem o cursor de volta ao início da linha) e FFs (que alguns dispositivos de exibição entendem como quebra de página) para LF para obter o mesmo comportamento que wc -L, mas ignorando os outros que de qualquer forma não podemos dizer que influência eles terão na largura da tela).

    Isso abrange TABs, mas não caracteres de largura simples ou dupla. Observe que a implementação GNU de expandatualmente não expande TABs corretamente se houver caracteres de vários bytes (muito menos de largura zero ou largura dupla).

    $ printf 'ééééé\t\n' | wc -L
    8
    $ printf 'ééééé\t\n' | expand | wc -L
    11
    

    Observe também que ./**/*.{c,h,p{l,y}}, por padrão, ignoraria arquivos ocultos ou arquivos em diretórios ocultos. À medida que a expansão do brace se expande para vários globs, você também obteria erros (fatal with zshor bash -O failglob) se um desses globs não corresponder.

    Com zsh, você usaria ./**/*.(c|h|p[ly])(D.)que é um glob e onde Dinclui arquivos ocultos e .restringe a arquivos regulares .

    Para uma solução que leva em consideração a largura real dos caracteres (supondo que todos os arquivos de texto sejam codificados na codificação de caracteres da localidade), você pode usar:

    git grep -h '' ./**/*.(c|h|p[ly])(.) | tr '\r\f' '\n\n' |
      perl -Mopen=locale -MText::Tabs -MText::CharWidth=mbswidth -lne '
        $n++ if mbswidth(expand($_)) > 80;
        END{print 0+$n}'
    

    Observe que, pelo menos em sistemas GNU, mbswidth()considera os caracteres de controle como tendo uma largura de -1e 1 para expand(). Assumimos que nenhum caractere de controle diferente de CR, NL, TAB, FF é encontrado nos arquivos.

    • 10
  3. Best Answer
    roaima
    2018-09-15T01:17:07+08:002018-09-15T01:17:07+08:00

    Se pudermos presumir pelo seu comentário que os caracteres de tabulação aparecerão apenas no início das linhas, podemos contar alternativas para um mínimo de 80 caracteres.

    • Sem guias, pelo menos 81 caracteres
    • Uma guia, pelo menos 73 caracteres
    • Duas guias, pelo menos 65 caracteres
    • etc.

    A confusão resultante é a seguinte, com sua awkdeclaração somando as contagens de linhas individuais para fornecer um total geral

    git grep -hcP '^(.{81,}|\t.{73,}|\t{2}.{65,}|\t{3}.{57,}|\t{4}.{49,}|\t{5}.{41,}|\t{6}.{33,}|\t{7}.{25,}|\t{8}.{17,}|\t{9}.{9,}|\t{10}.)' **/*.{c,h,p{l,y}} |
        awk '{ i+=$1 } END { printf ("%d\n", i) }'
    
    • 8
  4. user232326
    2018-09-16T06:23:20+08:002018-09-16T06:23:20+08:00

    Uma solução com ex (de vi ). Embora lento.

    Como o vi é capaz de processar corretamente dados UTF-8:

    Ele pode expandir as guias para espaços, contar os caracteres de controle como 1, processar \r \t \f \vcorretamente e também processar a maioria dos valores UNICODE válidos . Incluindo acentos compostos (NKC) e decompostos (NKD) e caracteres do cirílico, árabe, grego, chinês e muitos outros.

    $ cat script.sh
    #!/bin/bash --
    
    declare -i count=0
    
    for i do
        # Set ex script in one variable
        a='set expandtab        "       Expand tabs to spaces
           r '"$i"'             "       Read original file
           g/^.\{,80\}$/d       "       Remove all lines shorter than the value used
           wq                   "       Quit ' 
    
        o=outfile; :>"$o"           # Clean output file
        ex -s "$o" <<<"$a"          # process lines in $i file
        count+=$(wc -l <"$o")       # count and accumulate number of lines.
    done
    
    echo "$count"
    

    Chame o script como:

    $ script.sh     **/*.{c,h,p{l,y}}
    44984
    
    • 1

relate perguntas

  • resultados inesperados de `service | grep`

  • Leia o arquivo de texto com palavras e sua contagem de ocorrências e saída de impressão classificada

  • Comando ls | grep mostrando apenas diretórios (quando também deveria mostrar arquivos)

  • quando o grep conta e quando não

  • grep --line-buffered até X linhas?

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Como exportar uma chave privada GPG e uma chave pública para um arquivo

    • 4 respostas
  • Marko Smith

    ssh Não é possível negociar: "nenhuma cifra correspondente encontrada", está rejeitando o cbc

    • 4 respostas
  • Marko Smith

    Como podemos executar um comando armazenado em uma variável?

    • 5 respostas
  • Marko Smith

    Como configurar o systemd-resolved e o systemd-networkd para usar o servidor DNS local para resolver domínios locais e o servidor DNS remoto para domínios remotos?

    • 3 respostas
  • Marko Smith

    Como descarregar o módulo do kernel 'nvidia-drm'?

    • 13 respostas
  • Marko Smith

    apt-get update error no Kali Linux após a atualização do dist [duplicado]

    • 2 respostas
  • Marko Smith

    Como ver as últimas linhas x do log de serviço systemctl

    • 5 respostas
  • Marko Smith

    Nano - pule para o final do arquivo

    • 8 respostas
  • Marko Smith

    erro grub: você precisa carregar o kernel primeiro

    • 4 respostas
  • Marko Smith

    Como baixar o pacote não instalá-lo com o comando apt-get?

    • 7 respostas
  • Martin Hope
    rocky Como exportar uma chave privada GPG e uma chave pública para um arquivo 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Wong Jia Hau ssh-add retorna com: "Erro ao conectar ao agente: nenhum arquivo ou diretório" 2018-08-24 23:28:13 +0800 CST
  • Martin Hope
    Evan Carroll status systemctl mostra: "Estado: degradado" 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim Como podemos executar um comando armazenado em uma variável? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S Por que /dev/null é um arquivo? Por que sua função não é implementada como um programa simples? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 Como ver as últimas linhas x do log de serviço systemctl 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - pule para o final do arquivo 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla Por que verdadeiro e falso são tão grandes? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis Substitua a string em um arquivo de texto enorme (70 GB), uma linha 2017-12-30 06:58:33 +0800 CST
  • Martin Hope
    Bagas Sanjaya Por que o Linux usa LF como caractere de nova linha? 2017-12-20 05:48:21 +0800 CST

Hot tag

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve