ruby - libro - fahrenheit 451 ray bradbury
Convierte espacios sin ruptura a espacios en Ruby (6)
Tengo casos en los que los datos ingresados por el usuario desde un html textarea o entrada a veces se envían con /u00a0
(espacios sin interrupción) en lugar de espacios codificados como utf-8 json.
Creo que es un error en Firefox, ya que sé que el usuario no está intencionalmente colocando espacios sin interrupción en lugar de espacios.
También hay dos errores en Ruby, uno de los cuales se puede usar para combatir al otro.
Por cualquier razón, /s
no coincide con /u00a0
.
Sin embargo, [^[:print:]]
, que definitivamente no debería coincidir) y /xC2/xA0
ambos coincidirán, pero considero que son formas menos que ideales para tratar el problema.
¿Hay otras recomendaciones para evitar este problema?
Por cualquier razón, / s no coincide con / u00a0.
Creo que "sea cual sea la razón" es que no se supone que lo haga. Solo las clases de caracteres de construcciones POSIX y / p son conscientes de Unicode. Las abreviaturas de clase de caracteres no son:
Sequence As[...] Meaning
/d [0-9] ASCII decimal digit character
/D [^0-9] Any character except a digit
/h [0-9a-fA-F] Hexadecimal digit character
/H [^0-9a-fA-F] Any character except a hex digit
/s [ /t/r/n/f] ASCII whitespace character
/S [^ /t/r/n/f] Any character except whitespace
/w [A-Za-z0-9/_] ASCII word character
/W [^A-Za-z0-9/_] Any character except a word character
Aunque no está relacionado con Ruby (y no directamente con esta pregunta), el núcleo del problema podría ser que Alt + Space en Mac produzca un espacio sin interrupciones.
Esto puede causar todo tipo de comportamiento extraño (especialmente en la terminal).
Para aquellos que están interesados en más detalles, escribí " Por qué encadenar comandos con tuberías en Mac OS X no siempre funciona " sobre este tema hace algún tiempo.
Ejemplos de código IRB en funcionamiento real que responden a la pregunta, con los últimos Rubies (mayo de 2012)
Ruby 1.9
require ''rubygems''
require ''nokogiri''
RUBY_DESCRIPTION # => "ruby 1.9.3p194 (2012-04-20 revision 35410) [x86_64-linux]"
doc = ''<html><body> </body></html>''
page = Nokogiri::HTML(doc)
s = page.inner_text
s.each_codepoint {|c| print c, '' '' } #=> 32 160 32
s.strip.each_codepoint {|c| print c, '' '' } #=> 160
s.gsub(//s+/,'''').each_codepoint {|c| print c, '' '' } #=> 160
s.gsub(//u00A0/,'''').strip.empty? #true
Ruby 1.8
require ''rubygems''
require ''nokogiri''
RUBY_DESCRIPTION # => "ruby 1.8.7 (2012-02-08 patchlevel 358) [x86_64-linux]"
doc = ''<html><body> </body></html>''
page = Nokogiri::HTML(doc)
s = page.inner_text # " /302/240 "
s.gsub(//s+/,'''') # "/302/240"
s.gsub(//302/240/,'''').strip.empty? #true
Para las versiones antiguas de ruby (1.8.x), las correcciones son las que se describen en la pregunta.
Esto se soluciona en las versiones más nuevas de ruby 1.9+.
Si no puede usar /s
para espacio en blanco Unicode, eso es un error en la implementación de expresiones regulares de Ruby, porque de acuerdo con UTS # 18 "Expresiones regulares Unicode" Anexo C en Propiedades de compatibilidad a /s
, es absolutamente necesario que coincida con cualquier punto de código de espacio en blanco Unicode.
No hay margen de maniobra permitido ya que las dos columnas que detallan la Recomendación estándar y la Compatibilidad POSIX son las mismas para el caso. No puede documentar su decisión sobre esto: no está cumpliendo con el estándar Unicode, en particular, con el RL1.2a UTS # 18, si no lo hace.
Si no cumple con RL1.2a, no cumple con los requisitos de nivel 1, que son la funcionalidad más básica y elemental necesaria para usar expresiones regulares en Unicode. Sin eso, estás bastante perdido. Esta es la razón por la que existen los estándares. Mi recuerdo es que Ruby tampoco cumple con otros requisitos de Nivel 1. Por lo tanto, puede utilizar un lenguaje de programación que cumpla al menos el Nivel 1 si realmente necesita manejar Unicode con expresiones regulares.
Tenga en cuenta que no puede usar una propiedad de categoría general Unicode como /p{Zs}
para representar /p{Whitespace}
. Esto se debe a que la propiedad Whitespace es una propiedad derivada, no una categoría general. También hay caracteres de control incluidos en él, no solo separadores.
Use //u00a0/
para //u00a0/
espacios sin interrupciones. Por ejemplo, s.gsub(//u00a0/, '' '')
convierte todos los espacios que no se rompen en espacios regulares.
Utilice /[[:space:]]/
para hacer coincidir todos los espacios en blanco, incluido el espacio en blanco Unicode como espacios sin interrupción. Esto es diferente de //s/
, que solo coincide con el espacio en blanco ASCII.
Ver también: documentación Ruby Regexp