Comment créer une string avec des caractères unicode invalides, dans Zsh?

Pour certaines fins de test, j'ai besoin d'une string avec des caractères unicode invalides. Comment créer une telle string dans Zsh?

Je suppose que vous voulez dire des caractères Unicode encodés en UTF-8.

Cela dépend de ce que vous entendez par invalide .

invalid_byte_sequence=$'\x80\x81' 

C'est une séquence d'octets qui, par elle-même, n'est pas valide en encoding UTF-8 (le premier octet d'un caractère encodé en UTF-8 a toujours les deux bits les plus élevés). Cette séquence pourrait être vue au milieu d'un personnage, donc elle pourrait finir par former une séquence valide une fois concaténée à une autre séquence invalide comme $'\xe1' . $'\xe1' ou $'\xe1\x80' eux-mêmes seraient également invalides et pourraient être considérés comme un caractère tronqué.

 other_invalid_byte_sequence=$'\xc2\xc2' 

L'octet 0xc2 commence un caractère de 2 octets et 0xc2 ne peut pas être au milieu d'un caractère UTF-8. Cette séquence ne peut donc jamais être trouvée dans un text UTF-8 valide. Idem pour $'\xc0' ou $'\xc1' qui sont des octets qui n'apparaissent jamais dans le encoding UTF-8.

Pour les \uXXXX et \UXXXXXXXX , je suppose que l'enencoding de la locale actuelle est UTF-8.

 non_character=$'\ufffe' 

C'est l'un des 66 non-caractères actuellement spécifiés.

 not_valid_anymore=$'\U110000' 

Unicode est maintenant limité aux points de code jusqu'à 0x10FFFF. Et l'enencoding UTF-8 qui a été conçu à l'origine pour couvrir jusqu'à 0x7FFFFFFF ( perl supporte également une variante qui va à 0xFFFFFFFFFFFFFFFF) est maintenant classiquement limité à cela aussi.

 utf16_surrogate=$'\ud800' 

Les points de code 0xD800 à 0xDFFF sont des points de code réservés à l'enencoding UTF16. L'enencoding UTF-8 de ces points de code est donc invalide.

Maintenant, la plupart des points de code restants ne sont toujours pas assignés dans la dernière version d'Unicode.

 unassigned=$'\u378' 

Les nouvelles versions d'Unicode sont fournies avec de nouveaux caractères spécifiés. Par exemple Unicode 8.0 (publié en Juin 2015) a 🤗 ( U + 1F917 ) qui n'a pas été atsortingbué dans les versions antérieures.

 unicode_8_and_above_only=$'\U1f917' 

Quelques tests avec uconv :

 $ printf %s $invalid_byte_sequence| uconv -x any-name Conversion to Unicode from codepage failed at input byte position 0. Bytes: 80 Error: Illegal character found Conversion to Unicode from codepage failed at input byte position 1. Bytes: 81 Error: Illegal character found $ printf %s $other_invalid_byte_sequence| uconv -x any-name Conversion to Unicode from codepage failed at input byte position 0. Bytes: c2 Error: Illegal character found Conversion to Unicode from codepage failed at input byte position 1. Bytes: c2 Error: Truncated character found $ printf %s $non_character| uconv -x any-name \N{<noncharacter-FFFE>} $ printf %s $not_valid_anymore| uconv -x any-name Conversion to Unicode from codepage failed at input byte position 0. Bytes: f4 90 80 80 Error: Illegal character found $ printf %s $utf16_surrogate | uconv -x any-name Conversion to Unicode from codepage failed at input byte position 0. Bytes: ed a0 80 Error: Illegal character found $ printf %s $unassigned | uconv -x any-name \N{<unassigned-0378>} $ printf %s $unicode_8_and_above_only | uconv -x any-name \N{<unassigned-1F917>} $ 

Avec GNU grep , vous pouvez utiliser grep . pour voir s'il peut find un caractère dans l'input:

 l=(invalid_byte_sequence other_invalid_byte_sequence non_character not_valid_anymore utf16_surrogate unassigned unicode_8_and_above_only) for c ($l) print -r ${(P)c} | grep -q . && print $c 

Ce qui pour moi donne:

 non_character not_valid_anymore utf16_surrogate unassigned unicode_8_and_above_only 

C'est-à-dire que mon grep considère toujours certains de ces caractères invalides, non-caractères ou non-assignés comme étant des caractères (ou contenant). YMMV pour d'autres implémentations de grep ou d'autres utilitaires.