GNU wc -L
não trata TABs como 8 caracteres, ele trata TABs como seriam exibidos em um terminal com TAB pára a cada 8 colunas, então teria uma "largura" variando de 1 a 8 caracteres, dependendo de onde eles é encontrado na linha. wc -L
també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 \f
e \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 para o 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 as guias, mas não os caracteres de largura simples ou dupla. Observe que a implementação GNU de expand
atualmente não expande as TABs adequadamente se houver caracteres de múltiplos bytes (sem falar nos de largura zero ou de 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 ou arquivos ocultos em diretórios ocultos. À medida que a expansão da chave se expande para vários globs, você também obteria erros (fatais com zsh
ou bash -O failglob
) se esses globs não corresponderem.
Com zsh
, você usa ./**/*.(c|h|p[ly])(D.)
, que é um glob, e onde D
inclui arquivos ocultos e .
restringe-se a arquivos regulares .
Para uma solução que leva em conta a largura real dos caracteres (assumindo que todos os arquivos de texto estão codificados na codificação de caracteres do local), 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 nos sistemas GNU, mbswidth()
considera os caracteres de controle como tendo uma largura de -1
e 1 para expand()
. Assumimos que nenhum caracter de controle diferente de CR, NL, TAB, FF é encontrado nos arquivos.