¿Cómo reemplazar caracteres multibyte en Ruby usando gsub?

Tengo un problema al guardar registros en MongoDB usando Mongoid cuando contienen caracteres multibyte. Esta es la cadena:

a="Chris \xA5\xEB\xAE\xDFe\xA5"

Primero lo convierto a BINARIO y luego gsub es así:

a.force_encoding("BINARY").gsub(0xA5.chr,"oo")

... que funciona bien:

=> "Chris oo\xEB\xAE\xDFeoo"

Pero parece que no puedo usar el chr método si uso Regexp:

a.force_encoding("BINARY").gsub(/0x....?/.chr,"")
NoMethodError: undefined method `chr' for /0x....?/:Regexp

¿Alguien con el mismo problema?

Muchas gracias ...

preguntado el 12 de junio de 12 a las 09:06

entonces, ¿quieres reemplazar todos los caracteres que no son ascii con 'oo'? -

2 Respuestas

Puedes hacer eso con interpolación.

a.force_encoding("BINARY").gsub(/#{0xA5.chr}/,"") 

da

"Chris \xEB\xAE\xDFe"

EDITAR: según los comentarios, aquí hay una versión que traduce la cadena de codificación binaria a una representación ascii y hace una expresión regular en esa cadena

a.unpack('A*').to_s.gsub(/\\x[A-F0-9]{2}/,"")[2..-3] #=>"Chris "

el [2..-3] al final es para deshacerse del principio [" and and trailing "]

NOTA: para deshacerse de los caracteres especiales, también podría usar

a.gsub(/\W/,"") #=> "Chris"

Respondido el 14 de junio de 12 a las 11:06

Lo que tiene más sentido, aplicar chr a una cosa fibrosa, no a una expresión regular. - DGM

¡Sí, de hecho, tiene sentido! Sin embargo, ¿cómo puedo usar expresiones regulares para evitar especificar cada cadena de manera distintiva? - cacofonix

¿Cuál es el patrón que quieres usar? solo tiene que tratar los caracteres codificados como regulares, por ejemplo, gsub(/#{0xA5.chr}{2}/,"") reemplaza 0xA5 solo si ocurre 2 veces - peter

Quiero reemplazar los multibytes de una sola vez, usando algo como /0x....?/. Creo que este patrón describe todos los \xA5 \xEB \xAE \xDFe \xA5 - cacofonix

p a.force_encoding("BINARY").gsub(/#{0xA5.chr}...../,"") da "Chris" pero si quiere usar la presentación binaria como una cadena donde usa su patrón sobre tienes que empezar con una representación de cadena como b="Chris \\xA5\\xEB\\xAE\\xDF\\xA6" p b.gsub(/(\\x[0-9A-F]{2} )+/,"") #=>"Chris" - peter

La cadena real no contiene los caracteres literales \xA5: así es como se le muestran los caracteres que de otro modo no se podrían imprimir (similar cuando una cadena contiene una nueva línea que Ruby le muestra \n).

Si desea cambiar cualquier cosa que no sea ascii, puede hacer esto

a="Chris \xA5\xEB\xAE\xDFe\xA5"
a.force_encoding('BINARY').encode('ASCII', :invalid => :replace, :undef => :replace, :replace => 'oo')

Esto comienza forzando la cadena a la codificación binaria (siempre desea comenzar con una cadena donde los bytes son válidos para su codificación. El binario siempre es válido ya que puede contener bytes arbitrarios). Luego lo convierte a ASCII. Normalmente, esto generaría un error ya que hay caracteres con los que no sabe qué hacer, pero las opciones adicionales que hemos pasado le indican que reemplace las secuencias no válidas/indefinidas con los caracteres 'oo'

Respondido el 14 de junio de 12 a las 12:06

¡Gran sugerencia! ¡Gracias! - joseramonc

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.