引用符が最初の値の先頭または最後の値の末尾にある場合に備えて、正規表現はもう少し太字にする必要があります。
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"
上記の正規表現は、Ruby 1.9で使用可能なネガティブルックビハインドおよびネガティブルックアヘッドアサーション(アンカー)を使用しています。
(?<!^|,)
—このスポットの直前には^
、行頭()またはコンマを使用しないでください。
"
—二重引用符を見つける
(?!,|$)
—このスポットの直後には、コンマまたは行末($
)があってはなりません。
\1
ボーナスとして、実際にはどちらの側の文字もキャプチャしなかったので、置換文字列で正しく使用することを心配する必要はありません。
詳細については、Ruby正規表現の公式ドキュメントの「アンカー」のセクションを参照してください。
ただし、出力の一致を置き換える必要がある場合は、次のいずれかを使用できます。
"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>"
次のように、置換文字列で文字列補間を使用することはできません。
"hello".gsub /([aeiou])/, "<#{$1}>"
#=> "h<previousmatch>ll<previousmatch>"
…文字列補間は、が実行される前gsub
に1回行われるためです。ブロック形式を使用するとgsub
、一致ごとにブロックが再起動されます。この時点で、グローバル$1
が適切に入力され、使用できるようになります。
編集:Ruby 1.8の場合(一体なぜそれを使用しているのですか?)、次を使用できます:
puts csv.gsub(/([^,\n\r])"([^,\n\r])/,'\1""\2')