Le codage de caractères de votre environnement local (avec lequel vous pouvez dire locale charmap
) est un octet sur plusieurs octets.
Le plus courant de nos jours est UTF-8, où les caractères peuvent être codés sur 1 à 4 octets. Toutes les séquences d'octets ne forment pas des caractères valides dans UTF-8. Chaque caractère non-ASCII dans UTF-8 commence par un octet contenant les deux bits les plus élevés et indique le nombre d'octets avec le bit le plus élevé (mais pas le deuxième) suivi.
/dev/urandom
contient un flux aléatoire d'octets. tr
transliterates caractère, il doit donc décoder ces octets en tant que caractères. Les caractères ASCII de votre plage sont tous codés sur un caractère dans UTF-8, mais tr
doivent encore décoder tous les caractères. Il existe par exemple d'autres codages sur plusieurs octets dans lesquels certains caractères ne A
contiennent pas l'octet 0x41 (le code pour A
).
Parce que ce flux d'octets aléatoire est lié à contenir des séquences non valides (par exemple, un octet 0x80 seul n'est pas valide dans UTF-8 puisqu'un caractère non-ASCII doit commencer par un octet supérieur à 0xc1 (0xc0 et 0xc1 ne sont pas en UTF- 8 caractère)), tr
renvoie donc une erreur lorsque cela se produit.
Ce que vous voulez ici, c'est considérer ce flux d'octets comme des caractères dans un codage comportant un octet par caractère. Quelle que soit l'option choisie, tous les caractères de votre plage (en supposant par AZ, vous vouliez dire ABCDEFGHIJKLMNOPQRSTUVWXYZ et non des choses comme Ý
, Ê
) font partie du jeu de caractères portable afin d'être codés de la même manière dans tous les jeux de caractères pris en charge sur votre système.
Pour cela, vous devez créer la LC_CTYPE
variable de localisation qui est celui qui décide qui charset est utilisé et ce que les choses comme blank
, les alpha
classes de caractères contiennent. Mais pour la définition de la plage AZ, vous voudrez également définir la LC_COLLATE
variable (celle qui décide du classement des chaînes).
La locale C
aka POSIX
est celle qui garantit que les caractères sont des octets simples et AZ est ABCDEFGHIJKLMNOPQRSTUVWXYZ. Vous pourriez faire:
LC_CTYPE=C LC_COLLATE=C tr -dc 'A-Za-z0-9_!@#$%^&*()+=-'
(ici déplacer le -
à la fin, sinon, )-+
serait prendre comme une gamme comme A-Z
)
Mais notez que la LC_ALL
variable de l' emporte sur toutes les autres LC_*
et les LANG
variables. Donc, si LC_ALL
est déjà défini, ce qui précède n'aura aucun effet. Donc, au lieu de cela, vous pouvez simplement faire:
LC_ALL=C tr -dc 'A-Za-z0-9_!@#$%^&*()+=-'
Cela affectera d'autres éléments, tels que la langue des messages d'erreur, mais le changement de LC_CTYPE aurait peut-être déjà posé problème pour les messages d'erreur (par exemple, aucun moyen d'exprimer des messages d'erreur en russe ou en japonais dans le jeu de caractères de la langue C).
xargs
...