it-swarm.com.de

Wie grep ich für alle Nicht-ASCII-Zeichen?

Ich habe mehrere sehr große XML-Dateien und versuche, die Zeilen zu finden, die Nicht-ASCII-Zeichen enthalten. Ich habe folgendes versucht:

grep -e "[\x{00FF}-\x{FFFF}]" file.xml

Dabei wird jedoch jede Zeile in der Datei zurückgegeben, unabhängig davon, ob die Zeile ein Zeichen im angegebenen Bereich enthält.

Habe ich eine falsche Syntax oder mache ich etwas anderes falsch? Ich habe auch versucht:

egrep "[\x{00FF}-\x{FFFF}]" file.xml 

(mit einfachen und doppelten Anführungszeichen um das Muster).

320
pconrey

Sie können den Befehl verwenden: 

grep --color='auto' -P -n "[\x80-\xFF]" file.xml

Dies gibt Ihnen die Zeilennummer und markiert Nicht-ASCII-Zeichen rot.

In einigen Systemen funktioniert das Obige je nach Ihren Einstellungen nicht, so dass Sie mit dem Inversen arbeiten können

grep --color='auto' -P -n "[^\x00-\x7F]" file.xml

Beachten Sie auch, dass das wichtige Bit das -P-Flag ist, das --Perl-regexp: entspricht. Daher wird Ihr Muster als regulärer Perl-Ausdruck interpretiert. Das sagt auch das 

dies ist höchst experimentell und grep -P warnt vor nicht implementierten Eigenschaften.

429
jerrymouse

Anstatt Annahmen über den Bytebereich von Nicht-ASCII-Zeichen zu treffen, ist es, wie bei den meisten der oben genannten Lösungen, etwas besser, IMO statt des tatsächlichen Bytebereichs von ASCII -Zeichen explizit zu sein.

Die erste Lösung wäre zum Beispiel:

grep --color='auto' -P -n '[^\x00-\x7F]' file.xml

(was grundsätzlich für jedes Zeichen außerhalb des hexadezimalen Bereichs ASCII gilt: von\x00 bis\x7F)

Auf Mountain Lion funktioniert das nicht (aufgrund der fehlenden PCRE-Unterstützung in BSD grep) , aber wenn pcre über Homebrew installiert ist, wird Folgendes genauso funktionieren:

pcregrep --color='auto' -n '[^\x00-\x7F]' file.xml

Irgendwelche Vor- oder Nachteile, an die sich jeder denken kann?

105
pvandenberk

Folgendes funktioniert für mich:

grep -P "[\x80-\xFF]" file.xml

Nicht-ASCII-Zeichen beginnen bei 0x80 und gehen beim Anzeigen von Bytes auf 0xFF. Grep (und Familie) führen keine Unicode-Verarbeitung durch, um Multibyte-Zeichen in einer einzigen Entität zusammenzufassen, damit reguläre Ausdrücke gefunden werden können. Die Option -P in meinem grep ermöglicht die Verwendung von \xdd-Escape-Zeichen in Zeichenklassen, um das zu erreichen, was Sie möchten.

66
Thelema

In Perl

Perl -ane '{ if(m/[[:^ascii:]]/) { print  } }' fileName > newFile
47
noquery

Der einfachste Weg ist, ein Nicht-ASCII-Zeichen ... als ein Zeichen zu definieren, das kein ASCII -Zeichen ist.

LC_ALL=C grep '[^ -~]' file.xml

Fügen Sie nach dem ^ ggf. eine Registerkarte hinzu.

Durch das Setzen von LC_COLLATE=C werden böse Überraschungen über die Bedeutung von Zeichenbereichen in vielen Gebieten vermieden. Die Einstellung von LC_CTYPE=C ist erforderlich, um Single-Byte-Zeichen abzugleichen. Andernfalls würde der Befehl ungültige Bytefolgen in der aktuellen Codierung verpassen. Durch die Einstellung von LC_ALL=C werden alle vom Gebietsschema abhängigen Effekte vollständig vermieden.

35
Gilles

Hier ist eine andere Variante, die ich gefunden habe, die in der akzeptierten Antwort vollständig unterschiedliche Ergebnisse der grep-Suche nach [\x80-\xFF] erzeugt hat. Vielleicht ist es für jemanden nützlich, zusätzliche Nicht-ASCII-Zeichen zu finden:

grep --color='auto' -P -n "[^[:ascii:]]" myfile.txt

Hinweis: Die Grep-Funktion (ein Mac) auf meinem Computer verfügt nicht über die Option -P. Daher habe ich brew install grep ausgeführt und den oben genannten Aufruf mit ggrep anstelle von grep gestartet.

21
ryanm

Der folgende Code funktioniert:

find /tmp | Perl -ne 'print if /[^[:ascii:]]/'

Ersetzen Sie /tmp durch den Namen des Verzeichnisses, das Sie durchsuchen möchten.

8
user7417071

Suche nach nicht druckbaren Zeichen.

Ich stimme mit Harvey oben in den Kommentaren überein. Oft ist es sinnvoller, nach nicht druckbaren Zeichen zu suchen OR. Es ist leicht, an Nicht-ASCII zu denken, wenn Sie wirklich nicht druckbar sein sollten . Harvey schlägt vor, dass Sie Folgendes verwenden: "[^\n - ~]". Addieren Sie\r für DOS-Textdateien CR " 

Das Hinzufügen von -c (Anzahl der übereinstimmenden Muster anzeigen) zu grep ist auch hilfreich, wenn Sie nach nicht druckbaren Zeichen suchen, da die übereinstimmenden Zeichenfolgen das Terminal beeinträchtigen können.

Ich fand das Hinzufügen des Bereichs 0-8 und 0x0e-0x1f (zum Bereich 0x80-0xff) ein nützliches Muster. Hiervon ausgenommen sind TAB, CR und LF sowie ein oder zwei ungewöhnliche druckbare Zeichen. IMHO ein ziemlich nützliches (wenn auch grobes) grep-Muster ist DIESES:

grep -c -P -n "[\x00-\x08\x0E-\x1F\x80-\xFF]" *

nervenzusammenbruch:

\x00-\x08 - non-printable control chars 0 - 7 decimal
\x0E-\x1F - more non-printable control chars 14 - 31 decimal
\x80-1xFF - non-printable chars > 128 decimal
-c - print count of matching lines instead of lines
-P - Perl style regexps

Instead of -c you may prefer to use -n (and optionally -b) or -l
-n, --line-number
-b, --byte-offset
-l, --files-with-matches

Z.B. praktisches Anwendungsbeispiel find, um alle Dateien im aktuellen Verzeichnis zu finden:

find . -type f -exec grep -c -P -n "[\x00-\x08\x0E-\x1F\x80-\xFF]" {} + 

Sie können den Grep manchmal anpassen. z.B. BS (0x08 - Rückschritt) Zeichen, die in einigen druckbaren Dateien verwendet werden, oder um VT (0x0B - vertikales Register) auszuschließen. Die Zeichen BEL (0x07) und ESC (0x1B) können in einigen Fällen auch als druckbar angesehen werden.

Non-Printable ASCII Chars
** marks PRINTABLE but CONTROL chars that is useful to exclude sometimes
Dec   Hex Ctrl Char description           Dec Hex Ctrl Char description
0     00  ^@  NULL                        16  10  ^P  DATA LINK ESCAPE (DLE)
1     01  ^A  START OF HEADING (SOH)      17  11  ^Q  DEVICE CONTROL 1 (DC1)
2     02  ^B  START OF TEXT (STX)         18  12  ^R  DEVICE CONTROL 2 (DC2)
3     03  ^C  END OF TEXT (ETX)           19  13  ^S  DEVICE CONTROL 3 (DC3)
4     04  ^D  END OF TRANSMISSION (EOT)   20  14  ^T  DEVICE CONTROL 4 (DC4)
5     05  ^E  END OF QUERY (ENQ)          21  15  ^U  NEGATIVE ACKNOWLEDGEMENT (NAK)
6     06  ^F  ACKNOWLEDGE (ACK)           22  16  ^V  SYNCHRONIZE (SYN)
7     07  ^G  BEEP (BEL)                  23  17  ^W  END OF TRANSMISSION BLOCK (ETB)
8     08  ^H  BACKSPACE (BS)**            24  18  ^X  CANCEL (CAN)
9     09  ^I  HORIZONTAL TAB (HT)**       25  19  ^Y  END OF MEDIUM (EM)
10    0A  ^J  LINE FEED (LF)**            26  1A  ^Z  SUBSTITUTE (SUB)
11    0B  ^K  VERTICAL TAB (VT)**         27  1B  ^[  ESCAPE (ESC)
12    0C  ^L  FF (FORM FEED)**            28  1C  ^\  FILE SEPARATOR (FS) RIGHT ARROW
13    0D  ^M  CR (CARRIAGE RETURN)**      29  1D  ^]  GROUP SEPARATOR (GS) LEFT ARROW
14    0E  ^N  SO (SHIFT OUT)              30  1E  ^^  RECORD SEPARATOR (RS) UP ARROW
15    0F  ^O  SI (SHIFT IN)               31  1F  ^_  UNIT SEPARATOR (US) DOWN ARROW
3
gaoithe

Seltsamerweise musste ich das heute machen! Am Ende habe ich Perl benutzt, weil ich Grep/Egrep nicht zum Laufen bringen konnte (selbst im -P-Modus). So etwas wie:

cat blah | Perl -en '/\xCA\xFE\xBA\xBE/ && print "found"'

Verwenden Sie für Unicode-Zeichen (wie \u2212 im Beispiel unten) Folgendes:

find . ... -exec Perl -CA -e '$ARGV = @ARGV[0]; open IN, $ARGV; binmode(IN, ":utf8"); binmode(STDOUT, ":utf8"); while (<IN>) { next unless /\N{U+2212}/; print "$ARGV: $&: $_"; exit }' '{}' \;
1
dty

Wenn Sie alle Nicht-ASCII-Zeichen finden, haben Sie den Eindruck, dass Sie entweder nach Unicode-Zeichenfolgen suchen oder die Zeichen einzeln entfernen möchten.

Versuchen Sie eine der folgenden Optionen (die Variable file wird für die Automatisierung verwendet):

 file=file.txt ; LC_ALL=C grep -Piao '[\x80-\xFF\x20]{7,}' $file | iconv -f $(uchardet $file) -t utf-8

 file=file.txt ; pcregrep -iao '[\x80-\xFF\x20]{7,}' $file | iconv -f $(uchardet $file) -t utf-8

 file=file.txt ; pcregrep -iao '[^\x00-\x19\x21-\x7F]{7,}' $file | iconv -f $(uchardet $file) -t utf-8

Vanilla grep funktioniert nicht korrekt ohne LC_ALL = C, wie in den vorherigen Antworten angegeben.

ASCII-Bereich ist x00-x7F, Leerzeichen ist x20, da Zeichenfolgen Leerzeichen enthalten und der negative Bereich ihn nicht zulässt.

Der Nicht-ASCII-Bereich ist x80-xFF, da der positive Bereich durch Zeichenfolgen Leerzeichen enthält.

Es wird angenommen, dass Zeichenfolge mindestens 7 aufeinanderfolgende Zeichen innerhalb des Bereichs ist. {7,}.

Bei Shell-lesbaren Ausgaben gibt uchardet $file eine Schätzung der Dateicodierung zurück, die zur automatischen Interpolation an iconv übergeben wird.

0
noabody

Es könnte interessant sein zu wissen, wie man nach einem Unicode-Zeichen sucht. Dieser Befehl kann helfen. Sie müssen den Code nur in UTF8 kennen

grep -v $'\u200d'
0
arezae