Resumen: Perl, por defecto, no sabe qué es lo que está leyendo.
Te cuento lo que pasa. Cuando lees 'Facturación' desde una base de datos, ésta te devuelve esta ristra de bytes:
- 46 61 63 74 75 72 61 63 69 c3 b3 6e Facturación
Nosotros, como sabemos que la base de datos está codificada en utf8, vemos claramente que el carácter tildado 'ó' está codificado en dos bytes (
0xc3,
0xb3).
Pero Perl no lo sabe... Perl cree que esos son datos en codificación iso-8859-1 (latin 1), así que los guarda en la variable $UsuarioNom, como una simple ristra de bytes.
Luego, cuando le mandas imprimir el valor, recuerda que le pusimos que queremos que lo haga en codificación utf8. Como la variable $UsuarioNom es una ristra de bytes (no caracteres Unicode), Perl entonces hace transformación de código: de latin 1 a utf8, así que lo que emite es:
- 46 61 63 74 75 72 61 63 69 c3 83 c2 b3 6e Facturación
¿Por qué? Pues porque Perl tiene que transformar el byte
0xc3 -que él supone que es un carácter en latin 1- a un carácter en utf8, por lo que lo transforma en (
0xc3,
0x83). Y el byte
0xb3 lo transforma en (
0xc2,
0xb3).
Y el resultado final es que en pantalla vemos "caracteres raros", como lo llamas tú.
En cambio, cuando haces el decode(), le estás diciendo a Perl que lo que contiene la variable está en utf8, así que lo guarda de otra manera -una ristra de caracteres en Unicode-, y cuando más tarde lo mandas imprimir, hace la codificación de otra manera, y sale de la forma correcta.