it-swarm.com.de

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

Ist es möglich, Zeilen in einer Datei zu finden, die mehr als 79 Zeichen enthalten?

57
rowantran

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

grep '.\{80\}' file

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

awk 'length>79' file

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

Mit Ausnahme der Perl¹-Implementierung (oder der awk/grep/sed-Implementierungen (wie mawk oder Busybox), die nicht unterstützt werden Multi-Byte-Zeichen), das die Länge in Bezug auf die Anzahl von Zeichen (gemäß der Einstellung LC_CTYPE des Gebietsschemas) anstelle von Bytes zählt.

Wenn die Eingabe Bytes enthält, die nicht Teil gültiger Zeichen sind (was manchmal vorkommt, wenn der Zeichensatz des Gebietsschemas UTF-8 ist und die Eingabe eine andere Codierung aufweist), sind diese Bytes abhängig von der Lösung und der Tool-Implementierung zählt entweder als 1 Zeichen oder als 0 oder stimmt nicht mit . überein.

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

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

Das würde bedeuten, dass alle 4 Lösungen berücksichtigen, dass die obige Zeile 122 Zeichen enthält. Außer in den Tools Perl und GNU) treten immer noch potenzielle Probleme für Zeilen auf, die NUL-Zeichen (0x0 Byte) enthalten.


¹ Das Verhalten von Perl kann jedoch durch die Umgebungsvariable Perl_UNICODE beeinflusst werden

95
manatwork

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 das Zeilenumbruchzeichen \n Von den Berechnungen ausschließen möchten, können wir if len(line) > 79 zu if len(line.strip()) > 79 machen

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

1