Die Zeichencodierung Ihres Gebietsschemas (die Sie erkennen können locale charmap
) besteht aus einem Multi-Byte pro Zeichen.
Heutzutage ist UTF-8 am gebräuchlichsten, bei dem Zeichen über 1 bis 4 Bytes codiert werden können. Nicht alle Bytefolgen bilden in UTF-8 gültige Zeichen. Jedes Nicht-ASCII-Zeichen in UTF-8 beginnt mit einem Byte, in dem die zwei höchsten Bits gesetzt sind, und gibt an, wie viele Bytes mit dem höchsten (aber nicht dem zweithöchsten) gesetzten Bit folgen.
/dev/urandom
enthält einen zufälligen Strom von Bytes. tr
transkribiert Zeichen, daher müssen diese Bytes als Zeichen dekodiert werden. Diese ASCII-Zeichen in Ihrem Bereich sind alle in UTF-8 für ein Zeichen codiert, müssen jedoch tr
noch alle Zeichen decodieren. Es gibt zum Beispiel andere A
Mehrbyte -Codierungen, bei denen einige andere Zeichen als das 0x41-Byte (der Code für A
) enthalten.
Da dieser zufällige Bytestrom zwangsläufig ungültige Sequenzen enthält (zum Beispiel ist ein 0x80-Byte für sich in UTF-8 ungültig, da ein Nicht-ASCII-Zeichen mit einem Byte beginnen muss, das größer als 0xc1 ist (0xc0 und 0xc1 befinden sich in keinem UTF- 8 Zeichen)), wird also in diesem tr
Fall mit einem Fehler zurückgegeben.
Was Sie hier wünschen, ist, diesen Strom von Bytes als Zeichen in einer Kodierung zu betrachten, die ein Byte pro Zeichen hat. Unabhängig davon , welche Sie wählen , ist nicht wichtig , da alle diese Zeichen in Ihrem Bereich (unter der Annahme von AZ, Sie bedeutete ABCDEFGHIJKLMNOPQRSTUVWXYZ und nicht Dinge wie Ý
, Ê
) sind Teil des tragbaren Zeichensatz so das gleiche in allen charsets auf Ihrem System unterstützt codiert werden.
Dafür würden Sie die eingestellte LC_CTYPE
Lokalisierung Variable , die derjenige ist, der die charset entscheidet verwendet wird und welche Dinge wie blank
, alpha
Zeichenklassen enthalten. Für die Definition des AZ-Bereichs möchten Sie jedoch auch die LC_COLLATE
Variable festlegen (diejenige, die über die Reihenfolge der Zeichenfolgen entscheidet).
Das Gebietsschema C
aka POSIX
garantiert, dass Zeichen Einzelbytes sind, und AZ ist ABCDEFGHIJKLMNOPQRSTUVWXYZ. Du könntest es tun:
LC_CTYPE=C LC_COLLATE=C tr -dc 'A-Za-z0-9_!@#$%^&*()+=-'
(hier das -
ans ende verschieben, sonst )-+
wäre das als bereich zu nehmen wie A-Z
)
Beachten Sie jedoch, dass die LC_ALL
Variable alle anderen LC_*
und LANG
Variablen überschreibt . Wenn LC_ALL
also bereits etwas anderes definiert ist, hat das oben Gesagte keine Auswirkung. Also können Sie stattdessen einfach Folgendes tun:
LC_ALL=C tr -dc 'A-Za-z0-9_!@#$%^&*()+=-'
Dies wirkt sich auf andere Dinge wie die Sprache der Fehlermeldungen aus. Das Ändern von LC_CTYPE könnte jedoch bereits ein Problem für Fehlermeldungen gewesen sein (z. B. keine Möglichkeit, russische oder japanische Fehlermeldungen im Zeichensatz des Gebietsschemas C auszudrücken).
xargs
...