2016-11-25 3 views
1

So während jemand Code debuggen half mir erkannte ich, dass es einige seltsame Zeichen in ihrer Ausgabe waren, nämlich und (\ xc0 und \ xd0 in hex).Wie grep ich für Sonderzeichen (Steuerzeichen) mit Hexadezimal-Darstellung

Ich wollte diese Zeichen in einer großen Textausgabedatei finden.

Ich habe es geschafft, diese Zeichen mit erhabenen zu finden, indem Sie die Regex-Option in Find mit \xc0 oder \xd0 die Abfrage ist. Ich habe es auch geschafft, grep sie, indem Sie grep $'\xc0' filename in bash zu tun.

Das Ding, das mich stört, ist, dass, wenn ich die -P Option für grep verwende, es ablehnt, diese Zeichen zu finden.

grep -P "\xc0" filename würde nichts für eine Datei ausgeben, die dieses Zeichen darin hat (und die anderen beiden Methoden oben würden es erfolgreich finden), und das nervt mich so sehr, ich will wissen, warum das nicht funktionieren würde.

ich ein paar andere Beiträge, in denen zusammen mit "[\x80-\xff]" die -P Option vorgeschlagen gelesen haben, aber aus irgendeinem Grund bekomme ich konnte einfach nicht arbeiten, um sie: \

grep -P ein guter Freund für eine lange hat Zeit bis jetzt Jede Hilfe und Tipps sind willkommen

ich verwende GNU grep

EDIT :(:!.

I ha habe tatsächlich 2 Linux-Distributionen probiert.

  • auf Ubuntu 14.04 mit bash: Mein Terminal scheint nicht den Charakter zu mögen: \

printf "\xc0" druckt nichts im Terminal, Drucken es jedoch in einer Datei mit > und dann bei der Eröffnung erhaben würde den Charakter zeigen.

printf "\xc0" > foo 
grep $'\xc0' foo > out1 
grep -P '\xc0' foo > out2 
grep -P '\x{c0}' foo > out3 

out{1,2,3} sind alle leer.

  • auf CentOS 7.2 mit bash: printf druckt etwas - das Fragezeichen dunkel Dingen

printf "\xc0" druckt (sieht tatsächlich wie diese)

printf "\xc0" > foo 
grep $'\xc0' foo > out1 
grep -P '\xc0' foo > out2 
grep -P '\x{c0}' foo > out3 

Nur out1 den Charakter enthält.

+0

könnte ich wütend und unwillig klang in der ursprünglichen Nachricht zu lernen, aber ich lernen will :) Es gibt wahrscheinlich einige Vorbehalte mit 'grep -P' Ich weiß nicht, und ich würde mehr als glücklich sein zu finden, raus :) – a283626086

+0

'Ich konnte sie nur nicht zur Arbeit bringen? Welche Fehler haben Sie gesehen? – Inian

+0

Und hast du 'grep -P \ x {c0}" Dateiname "versucht? Oder sogar '" \ x {00c0} "'? –

Antwort

0

Byte

Was müssen Sie zuerst zu tun ist, innerhalb einer Variablen die genaue Byte, die Sie suchen möchten, erstellen.

So etwas wie irgendetwas davon:

a=$(echo -e '\xc0) 
a=$'\xc0' 
a=$(printf '\xc0') 
a=$(echo -e '\300')  # 300 is 0xC0 in octal 
a=$'\300' 
a=$(printf '\300') 
a=$(echo "c0" | xxd -r -p) 

Ich könnte versuchen, mit einigen anderen Möglichkeiten zu kommen, aber ich hoffe, Sie bekommen die Idee.

Dann könnten Sie versuchen, für die byte mit grep suchen:

echo $'Testing this: \xC0 byte' | grep "$a" 

Und wenn Sie ein Gebietsschema mit utf-8 verwenden (wie die häufigste ist), die scheitern. Wenn Sie eine ISO-8859-1 locale ändern, wird dies funktionieren:

LC_ALL=en_US.iso88591 echo $'Testing this: \xC0 byte' | 
LC_ALL=en_US.iso88591 grep -P "$a" 

Oder, wenn Sie nichts dagegen haben, eine neue bash-Instanz starten:

$ bash 
$ export LC_ALL=en_US.iso88591 
$ echo $'Testing this: \xC0 byte' | grep -P "$a" 

Und zurückzukehren, nur um die alte Bash-Umgebung durch Ausführen von .
Dies kann je nach System funktionieren oder nicht.

Lassen Sie uns auf die andere Seite erkunden: Zeichen.

Charakter

Es gibt eine sehr, sehr wichtige Wendung ist, dass Sie verstehen sollten.
Ein Byte ist kein Zeichen. Nun, manchmal, durch reines Glück, ist es.

Aber neben diesen 128 ASCII-Zeichen, in denen ein Byte ein Zeichen ist (nicht in UTF-16 oder UTF-32. Und vergessen wir auch EBCDIC), haben alle 1.114.112 (17 × 65.536) UNICODE-Codepunkte mehr als eins Byte 1.

In diesem Fall sollten Sie für den UNICODE-Codepunkt hex 0xC0 fragen.
In modernen bash, wie folgt aus:

$ printf '\U00C0` 
À 

Welche this character: LATIN CAPITAL LETTER A WITH GRAVE

Das heißt als ein Byte codiert werden, wenn die locale ISO-8859-1 (und ISO-8859-15, zumindest) und als zwei Bytes, wenn das Gebietsschema utf-8 ist.

$ a=$(printf '\UC0') 
$ printf 'Testing \U00C0 character' | grep -P "$a" 
Testing À character 

Es funktioniert auch, wenn Sie die Variable LC_ALL ändern. Nun, ich meine, dass grep das Zeichen erkennt, aber die gedruckte Zeile kann das Zeichen aufgrund des geänderten Gebietsschemas möglicherweise nicht korrekt darstellen.

Wenn die Datei hat Zeichen und die Codierung der Datei ist korrekt. Grep arbeitet mit dem Wert des Charakters in einer Variablen.

+0

Vielen Dank für die Erklärung! Ich bin immer mit Zeichenkodierungen und all dem verwirrt worden. Auf meinem Ubuntu-Rechner druckt 'printf' \ U00c0'' dieses Zeichen jetzt tatsächlich an mein Terminal. Also 'printf' \ xc0'' wurde nicht angezeigt, weil das Gebietsschema der Shell (ich konnte es in erhabener sehen, wenn ich in Datei gedruckt)? – a283626086

+0

Einer der Hauptgründe, warum ich verwirrt war, war, dass ich den '\ xc0' Regex-Ausdruck verwenden konnte, um nach dem Zeichen in Sublime zu suchen, während ich es anscheinend nicht mit' grep's '-P' Option machen kann. wie in vielen anderen Posts, die ich gesehen habe, zum Beispiel [dieser] (http://stackoverflow.com/questions/23695609/how-to-grep-for-presence-of-specific-hex-bytes-in-files) und [dieser] (http://unix.stackexchange.com/questions/19491/how-to-specify-characters-using-hexadecimal-codes-in-grep). – a283626086

+0

@ a283626086 Sie können '\ xc0' in sublime verwenden, da ** eine bestimmte Codepage (nur 256 Zeichen) angenommen wird, wahrscheinlich ISO-8859-1 (in USA) oder ISO-8859-5 (in Russland) oder ISO-8859-7 (Griechenland). In diesem begrenzten Zeichensatz bedeutet das Byte C0 ein spezifisches Zeichen À, Р oder ΐ (jeweils für die obigen Codeseiten). Das bedeutet aber auch, dass sich das verwendete Zeichen ändern kann, wenn eine Codepage geändert wird. Das Erhabene, das einen Zeichensatz auswählt, ist nur eine Einschränkung, die es hat. UTF-8 bricht diese Grenze. Umfassen UTF-8 und frei sein, irgendein Zeichen zu schreiben. – sorontar