Encontre todas as linhas que excedam um determinado comprimento

52

É possível encontrar linhas em um arquivo que exceda 79 caracteres?

rowantran
fonte

Respostas:

90

Em ordem decrescente de velocidade (em um sistema GNU em um código de idioma UTF-8 e em entrada ASCII) de acordo com meus testes:

grep '.\{80\}' file

perl -nle 'print if length$_>79' file

awk 'length>79' file

sed -n '/.\{80\}/p' file

Exceto pelo perl¹ (ou para awk/ grep/ sedimplementações (como mawkou ocupado) que não suporta caracteres de vários bytes), que conta o comprimento em termos de número de caracteres (de acordo com a LC_CTYPEconfiguração do código do idioma) em vez de bytes .

Se houver bytes na entrada que não fazem parte de caracteres válidos (o que acontece algumas vezes quando o conjunto de caracteres do código do idioma é UTF-8 e a entrada está em uma codificação diferente), dependendo da implementação da solução e da ferramenta, esses bytes contará como 1 caractere ou 0 ou não corresponderá ..

Por exemplo, uma linha que consiste em 30 asa 0x80 byte, 30 bs, um 0x81 byte e 30 UTF-8 és (codificado como 0xc3 0xa9), em um código de idioma UTF-8 não corresponderia .\{80\}ao GNU grep/ sed(como aquele 0x80 byte autônomo não corresponde .), teria um comprimento de 30 + 1 + 30 + 1 + 2 * 30 = 122 com perlou mawk3 * 30 = 90 com gawk.

Se você deseja contar em termos de bytes, corrija o código do idioma Ccom LC_ALL=C grep/awk/sed....

Isso teria todas as quatro soluções, considerando que a linha acima contém 122 caracteres. Exceto nas perlferramentas GNU, você ainda teria problemas em potencial nas linhas que contêm caracteres NUL (0x0 byte).


¹ o perlcomportamento pode ser afetado pela PERL_UNICODEvariável de ambiente

homem a trabalhar
fonte
O que você quer dizer com "eficiente"?
rowantran
Eu acho que manatwork significa digitar eficiência. awkpode se aproximar se você soltar ($0), o que está implícito de qualquer maneira;).
Thor
9
BTW, se você ancorar o regexp no início da linha ^, é um pouco mais rápido: por exemplo grep '^.\{80\}' file.
cas 29/07
4
A solução perl não considera codificação de tamanho variável, como UTF-8, diferente de todas as outras soluções.
BatchyX
6
Valores suficientemente grandes de N falham com grep, mas são bem-sucedidos com awk. (por exemplo, grep '^.\{1000\}' fileretornos grep: invalid repetition count(s), enquanto awk 'length>1000' filebem sucedido.)
mdahlman
1

Abordagem Shell:

while IFS= read -r line || [ -n "$line" ];
do 
    [ "${#line}" -gt 79 ] && printf "%s\n" "$line"
done < input.txt

Abordagem Python:

python -c 'import sys;f=open(sys.argv[1]);print "\n".join([ l.strip() for l in f if len(l) >79 ]);f.close()' input.txt

Ou como um script curto para facilitar a leitura:

#!/usr/bin/env python
import sys

with open(sys.argv[1]) as f:
    for line in f:
        if len(line) > 79:
            print line.strip()

Se quiséssemos excluir caractere de nova linha \na partir de cálculos, podemos fazer if len(line) > 79serif len(line.strip()) > 79

Nota lateral: esta é a sintaxe do Python 2.7. Use print()para Python 3

Sergiy Kolodyazhnyy
fonte