2012-02-01 21 views
16

ben her çift tırnak değil öncesinde veya "Ruby gsub Regexp birçok maçta nasıl kullanılır?

test,first,line,"you are a ""kind"" man",thanks 
again,second,li,"my ""boss"" is you",good 

yüzden "ile değiştirilir"" tarafından virgülle başarılı değiştirmeniz gerekiyor alıntılanan metnin

test,first,line,"you are a "kind" man",thanks 
again,second,li,"my "boss" is you",good 

içindeki çift tırnak sahip CSV dosyası içeriğe sahip "

Ben

x.gsub(/([^,])"([^,])/, "#{$1}\"\"#{$2}") 

b çalıştı ut

cevap

39

Kişisel regex durumda, biraz daha kalın olması gerekir fiyatları ilk değerin başlangıcında meydana veya son değer ucunda:

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" 

yukarıdaki normal ifade negatif olan ileriye dönük ve Ruby 1.9 uygun negatif ileri yönlü iddialar (çapa) kullanıyor.

  • (?<!^|,) - hemen hat (^) bir başlangıç ​​veya virgül
  • " ya olmamalıdır orada bu noktada önceki - bulmak bir çift tırnak
  • (?!,|$) - Hemen bu noktada şu ya olmamalıdır aslında iki tarafında karakterleri yakalamak etmediği bir virgül veya satır sonu ($)
  • bir bonus olarak

, bir endişelenmenize gerek yok Yedek dizginizde \1'u doğru kullanarak kullanın.

Daha fazla bilgi için, official Ruby regex documentation'daki "Çapalar" bölümüne bakın.


Ancak, çıktınıza eşleşmeleri yerine ihtiyacını yapmak durum için, size herhangi birini kullanabilirsiniz şunlardır:

"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>" 

Sen String interpolasyon kullanamazsınız yedek dize, senin gibi,:

"hello".gsub /([aeiou])/, "<#{$1}>" 
#=> "h<previousmatch>ll<previousmatch>" 

... bu dize enterpolasyon kez olur, çünkü 'dan önce gsub çalıştırıldı. gsub blok şeklinin kullanılması, her eşleşme için bloğu yeniden çağırır; bu noktada, global $1 uygun şekilde doldurulur ve kullanıma hazırdır.


Düzenleme: Ruby 1.8 için (neden yeryüzünde bunu kullanıyorsunuz?Eğer içeriğinde çift tırnak kullanıyoruz zaman '`' \ 1' gibi onları enquote için tek tırnak kullanmak \ 2'` muhtemelen daha iyi,

puts csv.gsub(/([^,\n\r])"([^,\n\r])/,'\1""\2') 
+0

Cool, Ruby'de olumsuz bakışta iddiaların nasıl yapılacağını anlamaya çalıştım ve anlayamadım. –

+1

Teşekkürler Phrogz, ruby ​​1,9 ile harika çalışıyor, ruby ​​1.8 için bir cevap tavsiye edebilir misiniz? –

+0

@MahmoudKhaled Ruby 1.8 ile çalışmak üzere güncellendi. (Gelecekte, Ruby'nin böyle eski bir versiyonuna ihtiyaç duyuyorsanız, lütfen sorunuza dahil edin. Ruby 1.9.1 - 1.9 serisinin ilk kararlı versiyonu - üç ** yıl önce yayınlandı **.) – Phrogz

8

s bir dizedir varsayarsak işe yaramadı, işe yarayacak:

puts s.gsub(/([^,])"([^,])/, "\\1\"\"\\2") 
+2

veya üçüncü formu'% kullanın:) kullanabilirsiniz q [\ 1 "" \ 2] ' – tadman

+1

Cevabımın aslında sizin durumunuz için yeterli olmayacağından endişeleniyorum çünkü pek çok şeyle başa çıkmıyor, sanki gerçekten bir virgül var mı? Verilerinizde alıntı yapın. Normal ifadelere dayanmayan daha karmaşık bir şey yapmanız gerekebilir. –