2012-02-01 7 views
16

मैं मैं हर दोहरे उद्धरण पहले या "कई मैचों के साथ ruby ​​gsub Regexp का उपयोग कैसे करें?

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

तो" की जगह एक "द्वारा" एक अल्पविराम से सफल नहीं प्रतिस्थापित करने की आवश्यकता उद्धृत पाठ

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

अंदर दोहरे उद्धरण चिह्नों होने csv फ़ाइल सामग्री है "

मैंने कोशिश की

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

ख केन्द्र शासित प्रदेशों के

उत्तर

39

आपका regex, थोड़ा और बोल्ड होने की जरूरत है मामले में उद्धरण पहले मूल्य के शुरू में पाए जाते हैं, या अंतिम मान के अंत में:

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" 

ऊपर regex नकारात्मक lookbehind और नकारात्मक अग्रदर्शी कथनों (एंकर) रूबी 1.9 में उपलब्ध उपयोग कर रहा है।

  • (?<!^|,) - एक दोहरे उद्धरण
  • (?!,|$) लगता है - - तुरंत इस स्थान वहाँ से ठीक पहले या तो लाइन (^) की एक शुरुआत या अल्पविराम
  • " नहीं होना चाहिए तुरंत इस स्थान के बाद वहाँ या तो नहीं होना चाहिए अल्पविराम या पंक्ति के अंत ($)

एक बोनस के रूप में, के बाद से आप वास्तव में दोनों तरफ पात्रों पर कब्जा नहीं किया है, तो आप एक चिंता करने की जरूरत नहीं है अपने प्रतिस्थापन स्ट्रिंग में \1 का उपयोग करके बोउट।

अधिक जानकारी के लिए, official Ruby regex documentation में "एंकर" अनुभाग देखें।


हालांकि, इस मामले में जहां आप अपने उत्पादन में मैच को बदलने के लिए जरूरत करना के लिए, आप में से किसी का उपयोग कर सकते हैं:

"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 चलाया गया है। gsub के ब्लॉक फॉर्म का उपयोग करके प्रत्येक मैच के लिए ब्लॉक को फिर से आमंत्रित किया जाता है, जिस बिंदु पर वैश्विक $1 उचित रूप से पॉप्युलेट किया गया है और उपयोग के लिए उपलब्ध है।


संपादित: रूबी 1.8 के लिए (क्यों पृथ्वी पर आपको लगता है कि प्रयोग कर रहे हैं?) आप का उपयोग कर सकते हैं:

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

कूल, मैंने यह पता लगाने की कोशिश की कि रूबी में नकारात्मक दिखने के तरीके को कैसे किया जाए और इसे समझ न सके। –

+1

धन्यवाद फोगज़, यह केवल रूबी 1.9 के साथ बहुत अच्छा काम करता है, क्या आप रूबी 1.8 के लिए उत्तर की सलाह दे सकते हैं? –

+0

@ महमूदखले रुबी 1.8 के साथ काम करने के लिए अपडेट किया गया। (भविष्य में, यदि आपको रूबी के इस तरह के एक प्राचीन संस्करण की आवश्यकता है, तो कृपया इसे अपने प्रश्न में शामिल करें। रूबी 1.9.1- 1.9 श्रृंखला का पहला स्थिर संस्करण तीन ** साल पहले जारी किया गया था।) – Phrogz

8

मान लिया जाये कि s एक स्ट्रिंग है काम नहीं किया, यह काम करेगा:

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

आप सामग्री में दोहरे उद्धरण चिह्नों का उपयोग कर रहे हैं, तो यह एकल उद्धरण का उपयोग करने के शायद बेहतर है उनकी तरह enquote को ' '\ 1" "\ 2'' या उपयोग करने वाले तृतीय रूप'% क्यू [\ 1 "" \ 2] ' – tadman

+1

मैं थोड़ा चिंतित हूं कि मेरा जवाब वास्तव में आपकी स्थिति के लिए पर्याप्त नहीं होगा क्योंकि यह बहुत सी चीज़ों को संभाल नहीं करता है, जैसे कि वास्तव में वास्तव में एक अल्पविराम है अपने डेटा में उद्धरण। आपको कुछ और जटिल करने की आवश्यकता हो सकती है जो रेगेक्स पर आधारित नहीं है। –

संबंधित मुद्दे