Eu já vi isso antes. Um inseto. Experimente:
--- tr.c 6 Sep 2005 23:04:11 -0000 1.10
+++ tr.c 30 May 2014 09:46:33 -0000
@@ -291,7 +291,6 @@
if(c<ccnt) code[c] = d;
if(d<ccnt && sflag) squeez[d] = 1;
}
- free(vect);
while((d = next(&string2)) != NIL) {
if(sflag) squeez[d] = 1;
if(string2.max==NIL && (string2.p==NULL || *string2.p==0))
(que foi de uma rápida olhada alguns meses atrás, enquanto esse patch vai te dar certo, eu não posso garantir que está certo. Aplique com patch -l
).
Agora observe também que /dev/urandom
fornece um fluxo de bytes . Em UTF-8, nem todas as sequências de bytes são mapeadas para caracteres válidos. Por exemplo, 0x41 0x81 0x41 não é válido porque 0x81
é >=
0x80, portanto, só pode ocorrer em uma sequência de 2 ou mais sobre 0x80 bytes.
Um byte inválido, porque não está no conjunto de caracteres que é o complemento de ☠, não será excluído por tr
.
Melhor seria provavelmente:
recode ucs-2..u8 < /dev/urandom | tr -cd ☠
ucs-2 sendo os caracteres U + 0000 a U + FFFF codificados em 2 bytes por caractere, /dev/urandom
se parece mais com um fluxo de caracteres ucs-2. (no entanto, estamos perdendo os caracteres U + 10000 para U + 10FFFF).
Mas isso ainda inclui o intervalo de pares substitutos D800..DFFF
qual mbrtowc(3)
vai sufocar (pelo menos com a minha versão da libc).
Esses pontos de código são reservados para o propósito de codificação UTF-16. O d800dc00, por exemplo, é a codificação UTF-16BE do U + 10000, mas não há U + D800 ou U + DC00. A codificação UTF-8 não faz sentido como um caractere (mesmo se adjacente).
Então você precisa excluí-los primeiro:
perl -ne 'BEGIN{$/=;binmode STDOUT,":utf8"}
$c = unpack("n",$_); if ($c < 0xd800 || $c > 0xdfff) {
no warnings "utf8"; print chr($c)
}' < /dev/urandom | tr -cd ☠
Se o objetivo for obter um fluxo de caracteres Unicode aleatórios codificados em UTF-8, é melhor obter um ponto de código aleatório no intervalo permitido (0.xx7ff, 0xf000..0x10ffff) e convertê-lo em UTF. -8. Se você quiser basear em /dev/urandom
, você pode usar 3 bytes (24 bits) para cada ponto de código:
perl -ne 'BEGIN{$/=;binmode STDOUT,":utf8"}
$c = unpack("N","--- tr.c 6 Sep 2005 23:04:11 -0000 1.10
+++ tr.c 30 May 2014 09:46:33 -0000
@@ -291,7 +291,6 @@
if(c<ccnt) code[c] = d;
if(d<ccnt && sflag) squeez[d] = 1;
}
- free(vect);
while((d = next(&string2)) != NIL) {
if(sflag) squeez[d] = 1;
if(string2.max==NIL && (string2.p==NULL || *string2.p==0))
$_") * 0x10F800 >> 24;
$c+=0x800 if $c >= 0xd800;
do {no warnings "utf8"; print chr($c)}' < /dev/urandom |
tr -cd ☠