Übereinstimmende Zeichenfolge mit einer festen Anzahl von Zeichen unter Verwendung von grep

9

Ich versuche alle 6Buchstabenwörter mit zu finden grep. Ich habe derzeit Folgendes:

grep "^.\{6\}$" myfile.txt 

Ich stelle jedoch fest, dass ich auch Ergebnisse erhalte wie: étuis, étude.

Ich vermute, es hat etwas mit den Symbolen über eden obigen Wörtern zu tun .

Kann ich etwas tun, um sicherzustellen, dass dies nicht geschieht?

Danke für Ihre Hilfe!


quelle

Antworten:

4

grepDie Vorstellung eines Charakters ist vom Gebietsschema abhängig . Wenn Sie sich in einem Nicht-Unicode-Gebietsschema befinden und aus einer Datei mit Unicode-Zeichen greifen, stimmt die Anzahl der Zeichen nicht überein. Wenn Sie echo $LANGdann sehen, sehen Sie das Gebietsschema, in dem Sie sich befinden.

Wenn Sie die Variablen LC_CTYPEund / oder LANGUmgebungsvariablen auf einen Wert setzen, der mit ".UTF-8" endet, erhalten Sie das richtige Verhalten:

$ cat data
étuis
letter
éééééé
$ LANG=C grep -E '^.{6}$' data
étuis
letter
$ LANG=en_US.UTF_8 grep -E '^.{6}$' data
letter
éééééé
$

Sie können Ihr Gebietsschema für nur einen Befehl ändern, indem Sie die Variable in derselben Zeile wie den Befehl zuweisen.

Bei dieser Konfiguration werden Multi-Byte-Zeichen als einzelne Zeichen betrachtet. Wenn Sie Nicht-ASCII-Zeichen vollständig ausschließen möchten, haben einige der anderen Antworten Lösungen für Sie.


Beachten Sie, dass es bei kombinierten Zeichen immer noch möglich ist, dass Dinge kaputt gehen oder zumindest nicht genau das tun, was Sie erwarten . Sie grepkönnen LATEINISCHEN KLEINBUCHSTABE E + KOMBINIERENDES CHARAKTER AKUT Oben anders behandeln als LATEINISCHER KLEINBUCHSTABE E MIT AKUT.

Michael Homer
quelle
Wenn Sie verwenden ., wird so etwas wie wăsd'sübereinstimmen
cuonglm
'ist ein Zeichen, das vernünftigerweise Teil einer "Zeichenfolge mit einer festen Anzahl von Zeichen" sein kann.
Michael Homer
Vielleicht. Und Sie sollten beide einstellen LC_CTYPEund so LANGetwas LC_CTYPE=en_US.UTF-8 LANG=en_USwird fehlschlagen. Zur LC_ALLSicherheit verwenden.
Cuonglm
2

Versuche dies:

LC_ALL=C.UTF-8 grep -x '[_[:alnum:]]\{6\}' file

-xVerwenden Sie diese Option, um die gesamte Zeile abzugleichen und von POSIX zu definieren (siehe grep ).

Sehen Sie hier für eine gute Erklärung, was der LC_ALLFall ist. Sie können utf-8 einstellen LANGoder LC_CTYPEverwenden, um das gleiche Verhalten zu erzielen. Der Auftragseingang ist LC_ALL=> LANG=> LC_CTYPE.

cuonglm
quelle
2

Mit GNU grepkönnen Sie mit PCRE-Unterstützung Folgendes tun:

grep -Px '\X{6}'

Stimmt .mit einem Zeichen \Xüberein , stimmt mit einem Ideogramm / Graphem überein.

In einem UTF-8-Gebietsschema:

$ locale charmap
UTF-8
$ printf '\u00e9tuis\n\u00e9tudes\n' | grep -Px '\X{6}'
études
$ printf 'e\u0301tuis\ne\u0301tudes\n' | grep -Px '\X{6}'
études

In letzterem étudesgibt es 7 Zeichen, 8 Bytes und 6 Graphems.

Stéphane Chazelas
quelle
Es scheint nicht zu funktionieren: echo épée | grep -Px '\X{6}'ouputépée
cuonglm
@Gnouc, Sie müssen das in einem UTF-8-Gebietsschema ausführen (wenn die éoben genannten in UTF-8 codiert wurden).
Stéphane Chazelas
Oh, meine Fehler. Es funktioniert mit UTF-8.
Cuonglm
0

Sie könnten etwas versuchen wie:

grep "^[A-Za-z]\{6\}$" myfile.txt

oder wenn die Wörter auch Zahlen enthalten können, dann:

grep "^[A-Za-z0-9]\{6\}$" myfile.txt

Fügen Sie einfach beliebige Zeichen zu den gewünschten eckigen Klammern hinzu.

Warwick
quelle
Dies étudestimmt überhaupt nicht mit dem überein , da das dem Akzent entsprechende ASCII-Zeichen den regulären Ausdruck durcheinander bringt.
Alex