Su expresión regular tiene que ser un poco más audaz, en caso de que las cotizaciones se producen al comienzo del primer valor, o al final del último valor:
csv = <<ENDCSV
test,first,line,"you are a "kind" man",thanks
again,second,li,"my "boss" is you",good
more,""Someone" said that you're "cute"",yay
"watch out for this",and,also,"this test case"
ENDCSV
puts csv.gsub(/(?<!^|,)"(?!,|$)/,'""')
#=> test,first,line,"you are a ""kind"" man",thanks
#=> again,second,li,"my ""boss"" is you",good
#=> more,"""Someone"" said that you're ""cute""",yay
#=> "watch out for this",and,also,"this test case"
la expresión regular anterior se utiliza de búsqueda hacia atrás negativo y afirmaciones de búsqueda hacia delante negativos (anclajes) disponibles en Ruby 1.9.
(?<!^|,)
- inmediatamente anterior este lugar no debe ser un comienzo de la línea (^
) o una coma
"
- encontrar una cotización doble
(?!,|$)
- inmediatamente después de este punto no debe ser una coma o al final de la línea ($
)
Como beneficio adicional, ya que en realidad no capturar los caracteres de cualquier lado, no es necesario que preocuparse de una Comience usando \1
correctamente en su cadena de reemplazo.
Para obtener más información, consulte la sección "Anclajes" en el official Ruby regex documentation.
Sin embargo, para el caso en que lo hace necesidad de reemplazar partidos en su salida, puede utilizar cualquiera de los siguientes:
"hello".gsub /([aeiou])/, '<\1>' #=> "h<e>ll<o>"
"hello".gsub /([aeiou])/, "<\\1>" #=> "h<e>ll<o>"
"hello".gsub(/([aeiou])/){ |m| "<#{$1}>" } #=> "h<e>ll<o>"
no puede utilizar cadena de interpolación en el cadena de reemplazo, como lo hizo:
"hello".gsub /([aeiou])/, "<#{$1}>"
#=> "h<previousmatch>ll<previousmatch>"
... porque eso interpolación de cadenas ocurre una vez, antes de se ejecutó gsub
. Utilizando la forma de bloque de gsub
vuelve a invocar el bloque para cada coincidencia, momento en el que el $1
global se ha rellenado de forma adecuada y está disponible para su uso.
Editar: para Ruby 1.8 (¿por qué en la tierra que está usando?) Se puede utilizar:
puts csv.gsub(/([^,\n\r])"([^,\n\r])/,'\1""\2')
Genial, traté de averiguar cómo hacer aseveraciones negativas en Ruby y no pude entenderlo. –
Gracias Phrogz, funciona muy bien con ruby 1.9 solamente, ¿puedes aconsejar una respuesta para ruby 1.8? –
@MahmoudKhaled Actualizado para trabajar con Ruby 1.8. (En el futuro, si necesita una versión tan antigua de Ruby, incluya esto en su pregunta. Ruby 1.9.1, la primera versión estable de la serie 1.9, se lanzó hace más de tres ** años **.) – Phrogz