2010-04-06 29 views
26

Tengo casos donde 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.Conversión de espacios sin rupturas a espacios en Ruby

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 utilizar para combatir al otro.

Por alguna razón, \s no coincide con \u00a0.

Sin embargo [^[:print:]], lo que definitivamente no debe coincidir) y \xC2\xA0 tanto coincidirá, pero considero que aquellos a ser menos que ideal formas de lidiar con el problema.

¿Hay otras recomendaciones para solucionar este problema?

+1

¿Qué versión de Ruby? En 1.9.2/\ u00a0/hace juego. – steenslag

+0

\ s no coincide \ u00a0 \ u00a0 coincide en 1.9, pero no estoy seguro acerca de 1.8 – CoolAJ86

+7

Regla # 1: cuando piensas que has encontrado un error en un programa extremadamente popular, especialmente en algo que se prueba y usado extensivamente, como el manejo de la textarea de Firefox, revise su prueba de manera muy silenciosa y cuidadosa. 99 veces de cada 100, el problema estará en su lado de la cerca. Cuando veo espacios sin interrupción aparecer en un campo de texto, donde es probable que la gente pegue el texto, sospecho que Microsoft Word o un editor que está configurado para sustituir   por espacios. Puede probar fácilmente su teoría creando una página, poner un área de texto en ella e intentar duplicar el problema. –

Respuesta

1

Para las versiones anteriores 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+.

+0

¿Puede obtener más específico? Acabo de tener el mismo problema en 1.9.3p194 que es bastante 1.9ish. \ n no coincide con unicode espacio no disruptivo, pero \ u00a0 lo hace. – nasmorn

2

Por cualquier razón \ s no coincide \ u00a0.

Creo que el "cualquier motivo" 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 
+2

Oh, se supone que ** **, está bien. Simplemente no lo hace. Ver mi respuesta – tchrist

+0

Hay una diferencia entre estar en una especificación y estar en el código. Si se supone que es o no debido a la especificación es un punto discutible en este momento, porque no está allí, y no importa cuánto queremos que esté allí, no lo hará hasta que alguien en el equipo central decida agregarlo . Entonces, la realidad es que no se supone que funcione porque no está codificado. Tal vez en futuras revoluciones eso cambie. Me gustaría ver que cumpla con las especificaciones, pero no me preguntan. –

+0

Esa es una interpretación realmente extraña de las cosas. Tchrist es absolutamente correcto, y decir que algo "no debería funcionar" porque actualmente no funciona es la mejor verdad vacía que he leído en mucho tiempo. De cualquier manera: gsub en [[: espacio:]] hasta que alguien haga que Ruby realmente cumpla con los estándares. – owenmarshall

6

Si no puede utilizar \s para Unicode los espacios en blanco, eso es un error en la implementación de expresiones regulares Ruby, porque según UTS#18 “Unicode Regular Expressions” Annex C on Compatibility Properties un \s, es absolutamente necesaria para adaptarse a cualquier espacio en blanco Unicode punto de código

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 \s. No puede documentar su decisión sobre esto: no está cumpliendo con el estándar Unicode, en particular, con UTS # 18 RL1.2a, 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. Es por eso 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.

2

ejemplos reales de código de funcionamiento del IRB que responden a la pregunta, con las últimas rubíes (Mayo 2012)

Rubí 1.9

require 'rubygems' 
require 'nokogiri' 
RUBY_DESCRIPTION # => "ruby 1.9.3p194 (2012-04-20 revision 35410) [x86_64-linux]" 
doc = '<html><body> &nbsp; </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 

Rubí 1,8

require 'rubygems' 
require 'nokogiri' 
RUBY_DESCRIPTION # => "ruby 1.8.7 (2012-02-08 patchlevel 358) [x86_64-linux]" 
doc = '<html><body> &nbsp; </body></html>' 
page = Nokogiri::HTML(doc) 
s = page.inner_text # " \302\240 " 
s.gsub(/\s+/,'') # "\302\240" 
s.gsub(/\302\240/,'').strip.empty? #true 
37

Uso /\u00a0/ para que coincida con los espacios de no separación. Por ejemplo, s.gsub(/\u00a0/, ' ') convierte todos los espacios sin interrupción a espacios regulares.

Utilice /[[:space:]]/ para que coincida con todos los espacios en blanco, incluido el espacio en blanco Unicode como espacios sin interrupciones. Esto es diferente de /\s/, que solo coincide con el espacio en blanco ASCII.

Consulte también: Ruby Regexp documentation

+0

Mira en http://www.unicode.org/versions/Unicode6.2.0/ch06.pdf - Personajes espaciales. Pero la identificación parece incompleta –

+0

Se corrigió mi respuesta para simplemente usar '[[: espacio]]' (nota a sí mismo: no '[: espacio]'). –

+0

"s.gsub (/ \ u00a0 /, '')" es lo que he estado buscando. –

1

Aunque no relacionado con Ruby (y no directamente a esta pregunta), el núcleo del problema podría ser que Alt + espacio en los Mac produce una no separación espacio.

Esto puede causar todo tipo de comportamiento extraño (especialmente en el terminal).

Para aquellos que estén interesados ​​en más detalles, escribí "Why chaining commands with pipes in Mac OS X does not always work" sobre este tema hace algún tiempo.

Cuestiones relacionadas