2014-07-10 5 views
5

दो gsub की उपज अलग-अलग परिणाम। क्या कोई समझा सकता है क्यों?रुबी जीएसयूबी प्रतिस्थापन में असंगत व्यवहार?

कोड https://gist.github.com/franklsf95/6c0f8938f28706b5644d पर भी उपलब्ध है।

ver = 9999 
    str = "\t<key>CFBundleDevelopmentRegion</key>\n\t<string>en</string>\n\t<key>CFBundleVersion</key>\n\t<string>0.1.190</string>\n\t<key>AppID</key>\n\t<string>000000000000000</string>" 
    puts str.gsub /(CFBundleVersion<\/key>\n\t.*\.).*(<\/string>)/, "#{$1}#{ver}#{$2}" 
    puts '--------' 
    puts str.gsub /(CFBundleVersion<\/key>\n\t.*\.).*(<\/string>)/, "#{$1}#{ver}#{$2}" 

मेरे गहरे लाल रंग का संस्करण ruby 2.1.2p95 (2014-05-08 revision 45877) [x86_64-darwin13.0] (एमआरआई) है। मेरी मशीन पर, परिणाम है:

<key>CFBundleDevelopmentRegion</key> 
<string>en</string> 
<key>9999 
<key>AppID</key> 
<string>000000000000000</string> 
-------- 
<key>CFBundleDevelopmentRegion</key> 
<string>en</string> 
<key>CFBundleVersion</key> 
<string>0.1.9999</string> 
<key>AppID</key> 
<string>000000000000000</string> 

दूसरा वांछित प्रभाव है, लेकिन पहला गलत है।

उत्तर

8

इसे समय और कैसे रूबी regexes काम के साथ करना है।

gsub$1 और $2 सेट करता है, लेकिन पूरा होने के बाद तक नहीं। तो जब आप पहली बार दौड़ते हैं, तो वे खाली होते हैं। जब आप दूसरी बार दौड़ते हैं, तो वे पिछले gsub द्वारा सेट किए गए थे। आप जगह में regex कैप्चर करना चाहते हैं, तो आप \1 और \2 की जरूरत है, इस तरह:

puts str.gsub /(CFBundleVersion<\/key>\n\t.*\.).*(<\/string>)/, '\1' + ver.to_s + '\2' 
+0

कि पता करने के लिए बहुत अच्छा है, +1 :) – zx81

+1

तुम भी' gsub' के ब्लॉक फार्म का उपयोग कर सकता है।।। /) {"# {$ 1} # {ver} # {$ 2}"} ' – matt

+0

ब्लॉक फॉर्म के बारे में नहीं सोचा था, यह एक अच्छा मुद्दा है। –

1

आप gsub() के ब्लॉक फार्म का उपयोग करते हैं, तो आपका कोड सही तरीके से काम करेगा:

ver = 9999 

str = "\t<key>CFBundleDevelopmentRegion</key>\n\t<string>en</string>\n\t<key>CFBundleVersion</key>\n\t<string>0.1.190</string>\n\t<key>AppID</key>\n\t<string>000000000000000</string>" 

puts str.gsub(/(CFBundleVersion<\/key>\n\t.*\.).*(<\/string>)/) {|match| 
    "#{$1}#{ver}#{$2}" 
} 

puts '-' * 20 

puts str.gsub(/(CFBundleVersion<\/key>\n\t.*\.).*(<\/string>)/) {|match| 
    "#{$1}#{ver}#{$2}" 
} 

--output:-- 
    <key>CFBundleDevelopmentRegion</key> 
    <string>en</string> 
    <key>CFBundleVersion</key> 
    <string>0.1.9999</string> 
    <key>AppID</key> 
    <string>000000000000000</string> 
-------------------- 
    <key>CFBundleDevelopmentRegion</key> 
    <string>en</string> 
    <key>CFBundleVersion</key> 
    <string>0.1.9999</string> 
    <key>AppID</key> 
    <string>000000000000000</string> 

इस तरह के $के रूप में

तो प्रतिस्थापन एक स्ट्रिंग, ... है हालांकि, प्रतिस्थापन के भीतर विशेष मैच चर,: डॉक्स इस व्यवहार का वर्णन, वर्तमान मिलान का संदर्भ नहीं देगा।

...

ब्लॉक रूप में, वर्तमान मैच स्ट्रिंग एक पैरामीटर के रूप में पारित हो जाता है, और चर इस तरह के $ 1, $ 2, $ `, $ &, और $ 'के रूप में उचित रूप से का गठन किया जाएगा । ब्लॉक द्वारा लौटाए गए मान को प्रत्येक कॉल पर के लिए प्रतिस्थापित किया जाएगा। \ N \ t `str.gsub (/ (CFBundleVersion <\/key> * \) * (<\/string>):

+0

ऐसा इसलिए है क्योंकि ब्लॉक को निष्पादित करने से पहले रेगेक्स मिलान किया जाता है, लेकिन जब गैर-ब्लॉक फॉर्म में तर्क gsub को पास किया जाता है तब नहीं किया जाता है? –

+0

^ऐसा लगता है कि यह मामला है। – franklsf95

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