Trouver des lignes dépassant une certaine longueur

53

Est-il possible de trouver dans un fichier des lignes de plus de 79 caractères?

Rowantran
la source

Réponses:

91

Par ordre de vitesse décroissante (sur un système GNU dans une locale UTF-8 et sur une entrée ASCII) en fonction de mes tests:

grep '.\{80\}' file

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

awk 'length>79' file

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

Sauf pour les implémentations perl¹ one (ou pour awk/ grep/ sed(comme mawkou busybox) qui ne prennent pas en charge les caractères multi-octets), la longueur est comptée en nombre de caractères (en fonction du LC_CTYPEparamètre d'environnement local) et non en octets .

S'il y a des octets dans l'entrée qui ne font pas partie de caractères valides (ce qui arrive parfois lorsque le jeu de caractères de l'environnement local est UTF-8 et que l'entrée est dans un codage différent), ces octets dépendent de l'implémentation de la solution et de l'outil. comptera pour 1 caractère, ou 0 ou ne correspondra pas ..

Par exemple, une ligne composée de 30 aoctets 0x80, 30 bs, un octet 0x81 et de 30 UTF-8 é(codés en tant que 0xc3 0xa9) dans une locale UTF-8 ne correspond pas .\{80\}à GNU grep/ sed(cet octet autonome 0x80). ne correspond pas .), aurait une longueur de 30 + 1 + 30 + 1 + 2 * 30 = 122 avec perlou mawk, 3 * 30 = 90 avec gawk.

Si vous souhaitez compter en octets, corrigez les paramètres régionaux Cavec LC_ALL=C grep/awk/sed....

Cela aurait toutes les 4 solutions considérer que la ligne ci-dessus contient 122 caractères. Sauf dans perlet dans les outils GNU, des problèmes pourraient subsister pour les lignes contenant des caractères NUL (octet 0x0).


¹ le perlcomportement peut être affecté par la PERL_UNICODEvariable d'environnement si

homme au travail
la source
Qu'entendez-vous par "efficace"?
rowantran
Je pense que manatwork signifie efficacité de frappe. awkpeut venir plus près si vous laissez tomber ($0), ce qui est implicite de toute façon;).
Thor
9
Au fait, si vous ancrez l'expression rationnelle au début de la ligne ^, c'est un peu plus rapide: par exemple grep '^.\{80\}' file.
cas le
4
La solution perl ne prend pas en compte le codage à taille variable tel que UTF-8, contrairement à toutes les autres solutions.
BatchyX
6
Des valeurs suffisamment grandes de N échouent avec grep mais réussissent avec awk. (par exemple, grep '^.\{1000\}' fileretourne grep: invalid repetition count(s), tant que awk 'length>1000' fileréussit.)
mdahlman
1

Approche Shell:

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

Approche 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 comme un court script pour la lisibilité:

#!/usr/bin/env python
import sys

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

Si nous voulions exclure le caractère \nde nouvelle ligne des calculs, nous pouvons faire en if len(line) > 79sorte queif len(line.strip()) > 79

Note secondaire: il s'agit de la syntaxe Python 2.7. Utiliser print()pour Python 3

Sergiy Kolodyazhnyy
la source