2016-05-04 11 views
1

Ich habe eine Datei mit dieser Zeichenfolge in einer Zeile: „Ávila“Awk tolower eine Zeichenfolge, die mit einem Akzent beginnt - Unterstützung für ausländische Zeichen

Und ich möchte diese Ausgabe erhalten: „ávila“ .

Das Problem ist, dass die Funktion tolower von awk nur funktioniert, wenn die Zeichenfolge nicht mit Akzent beginnt, und ich muss awk verwenden.

Zum Beispiel, wenn ich awk tun 'BEGIN {print tolower ("Ávila")}' dann bekomme ich "Ávila" statt "ávila", das ist, was ich erwarte.

Aber wenn ich awk tun 'BEGIN {print tolower ("Castellón")}' dann ich "CASTELLO" get

+0

Mit gnu awk 4.0.1 bekomme ich "ávila" von 'tolower (" Ávila ")'. –

+0

Nebenbei: das Problem ist nicht mit der _position_ des fremden Zeichens in der Zeichenfolge verbunden (in Ihrem 2. Befehl war der ausländische Buchstabe bereits Kleinbuchstaben), aber zu der grundlegenden Unfähigkeit, Nicht-ASCII-Buchstaben als Buchstaben in bestimmten zu erkennen 'awk' Implementierungen. – mklement0

Antwort

2

Für eine gegebene awk Implementierung richtig mit Nicht-ASCII-Zeichen zu arbeiten (Fremd Buchstaben), muss die Zeichencodierung des aktiven Gebietsschemas berücksichtigt werden, wie in der (effektiven) LC_CTYPE Einstellung (Lauf locale, um es zu sehen).

Heute verwenden die meisten Locales UTF-8-Codierung, eine Multi-Byte-on-Demand-Codierung, die im ASCII-Bereich ein einzelnes Byte ist und 2 bis 4 Byte für alle anderen Unicode-Zeichen verwendet.
So für eine gegebene awk Implementierung nicht-ASCII zu erkennen (mit Akzent, ausländische) Buchstaben, muss es in der Lage sein mehrere Bytes als einzelnes Zeichen zu erkennen.

Zu den wichtigsten awk Implementierungen,

  • GNU Awk (gawk), die standardmäßig auf einige Linux-Distributionen
  • BSD awk, als auch unter OS X verwendet
  • Mawk (mawk), der Standard auf Debian-basierten Linux-Distributionen wie Ubuntu

nur GNU Awk Griffe richtig UTF8-codierte Zeichen (und vermutlich andere Codierung, wenn in der locale angegeben):

$ echo ÁvilA | gawk '{print tolower($0)}' 
ávila # both Á and A lowercased 

Umgekehrt wollen, wenn Sie ausdrücklich Zeichenverarbeitung auf ASCII begrenzen nur , prepend LC_CTYPE=C:

$ echo ÁvilA | LC_CTYPE=C gawk '{print tolower($0)}' 
Ávila # only ASCII char. A lowercased 

Praktische Ratschläge:

  • Um zu bestimmen, was die Umsetzung Ihrer Standard awk ist, laufen awk --version.

    • Im Fall von Mawk erhalten Sie eine Fehlermeldung erhalten, weil es nur Informationen Druckversion mit -W version unterstützt, aber das Fehlermeldung das Wort mawk enthalten.
  • I f möglich, Installation und Verwendung von GNU Awk (und optional der Standard macht awk); es ist für die meisten Unix-ähnlichen Plattformen verfügbar; z.B .:

    • Auf Debian-basierten Plattformen wie Ubuntu: sudo apt-get install gawk
    • Unter OS X mit Homebrew: brew install gawk.
  • Wenn Sie entweder BSD Awk oder Mawk, verwenden Sie die oben LC_CTYPE=C Ansatz zu sicherzustellen, dass die Multi-Byte-UTF-8-Zeichen sind mindestens durchlaufen ohne Änderungen verwenden.[1], aber fremde Buchstaben werden NICHT als Buchstaben erkannt (und werden daher in diesem Fall nicht kleingeschrieben).


[1] BSD Awk und Mawk auf O X (letztere eigentümlich nicht auf Linux) behandeln UTF-8-codierte Zeichen wie folgen:

  • Jedes Byte wird fälschlicherweise als sein eigenes Zeichen interpretiert.
  • Wenn nachdem das hohe Bit ignorieren, der resultierende Byte-Wert fällt in den Bereich von ASCII Großbuchstaben, wird auf den Wert 32ursprünglichen Byte hinzugefügt, um das Kleingegenstück zu erhalten.

In dem Fall auf der Hand, dies bedeutet:

  • Á ist Unicode Codepoint U+00C1, dessen UTF-8-Codierung ist die 2-Byte-Sequenz: 0xC3 0x81.

  • 0xC3: Dropping das hohe Bit (0xC3 & 0x7F) ergibt 0x43, die als ASCII-Buchstaben interpretiert C und 32 (0x20) zum daher ursprünglichen Wert, hinzugefügt Nachgeben 0xE3 (0xC3 + 0x20).

  • 0x81: Dropping das hohe Bit (0x81 & 0x7F) ergibt 0x1, die nicht im Bereich von ASCII Großbuchstaben ist (65-90, 0x41-0x5a), so wird das Byte bleibt wie sie ist.Das erste Byte wird effektiv von 0xC3 zu 0xE3 geändert, während das zweite Byte unberührt bleibt; Da 0xC3 0x81nicht ein korrekt UTF-8-codiertes Zeichen ist, wird das Terminal stattdessen ? drucken, um dies zu signalisieren.