Suchen Sie nach Zeilen, die eine bestimmte Länge überschreiten

52

Können in einer Datei Zeilen mit mehr als 79 Zeichen gefunden werden?

Rowantran
quelle

Antworten:

89

In der Reihenfolge abnehmender Geschwindigkeit (auf einem GNU-System in einem UTF-8-Gebietsschema und auf ASCII-Eingabe) nach meinen Tests:

grep '.\{80\}' file

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

awk 'length>79' file

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

Mit Ausnahme von perl¹ one (oder von awk/ grep/ -Implementierungen sed(like mawkoder busybox), die keine Mehrbyte-Zeichen unterstützen), wird die Länge in Form der Anzahl der Zeichen (gemäß der LC_CTYPEEinstellung des Gebietsschemas) anstelle von Bytes gezählt .

Wenn die Eingabe Bytes enthält, die nicht Teil gültiger Zeichen sind (was manchmal der Fall ist, wenn der Zeichensatz des Gebietsschemas UTF-8 ist und die Eingabe in einer anderen Codierung erfolgt), sind diese Bytes abhängig von der Lösung und der Toolimplementierung zählt entweder als 1 Zeichen oder als 0 oder stimmt nicht überein ..

Beispielsweise würde eine Zeile, die aus 30 asa 0x80 Byte, 30 bs, einem 0x81 Byte und 30 UTF-8 és (codiert als 0xc3 0xa9) in einem UTF-8-Gebietsschema besteht, nicht .\{80\}mit GNU grep/ sed(als dieses eigenständige 0x80 Byte) übereinstimmen passt nicht .), hätte eine Länge von 30 + 1 + 30 + 1 + 2 * 30 = 122 mit perloder mawk3 * 30 = 90 mit gawk.

Wenn Sie in Bytes zählen möchten, setzen Sie das Gebietsschema auf Cmit LC_ALL=C grep/awk/sed....

Das hätte alle 4 Lösungen in Betracht gezogen, dass die obige Zeile 122 Zeichen enthält. Mit Ausnahme von perlIn- und GNU-Werkzeugen haben Sie immer noch potenzielle Probleme mit Zeilen, die NUL-Zeichen (0x0-Byte) enthalten.


¹ Das perlVerhalten kann jedoch durch die PERL_UNICODEUmgebungsvariable beeinflusst werden

Mann bei der Arbeit
quelle
Was meinst du mit "effizient"?
Rowantran
Ich denke, Handarbeit bedeutet Effizienz beim Tippen. awkkann näher kommen, wenn du fällst ($0), was sowieso implizit ist;).
Thor
9
Übrigens, wenn Sie den regulären Ausdruck am Zeilenanfang mit verankern ^, ist dies etwas schneller: z grep '^.\{80\}' file.
cas
4
Die Perl-Lösung berücksichtigt im Gegensatz zu allen anderen Lösungen keine Kodierung mit variabler Größe wie UTF-8.
BatchyX
6
Ausreichend große Werte von N schlagen mit grep fehl, sind aber mit awk erfolgreich. (zB grep '^.\{1000\}' filekehrt zurück grep: invalid repetition count(s), solange awk 'length>1000' fileerfolgreich.)
mdahlman
1

Shell-Ansatz:

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

Python-Ansatz:

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

Oder als kurzes Skript zur besseren Lesbarkeit:

#!/usr/bin/env python
import sys

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

Wenn wir Newline - Zeichen ausschließen wollte \nvon Berechnungen, können wir machen if len(line) > 79werdenif len(line.strip()) > 79

Anmerkung: Dies ist die Python 2.7-Syntax. Verwenden Sie print()für Python 3

Sergiy Kolodyazhnyy
quelle