2012-07-16 19 views
5

मैं इस तरह एक स्ट्रिंग है:रेगेक्स के साथ कुछ कैसे मेल करें जो दो विशेष पात्रों के बीच नहीं है?

a b c एक ख "एक ख" ख एक "एक"

कैसे मैं हर a कि एक स्ट्रिंग " द्वारा सीमांकित का हिस्सा नहीं है से मेल करते हैं?

एक बीसी एक ख "ab" ख एक "एक"

मैं उन मैचों बदलना चाहते हैं (या बल्कि निकालें: मैं यहाँ सब कुछ बोल्ड है कि मिलान करना चाहते हैं उन्हें एक खाली स्ट्रिंग के साथ बदलकर), इसलिए मेल खाने के लिए उद्धृत भागों को हटा देना काम नहीं करेगा, क्योंकि मैं चाहता हूं कि वे स्ट्रिंग में बने रहें। मैं रूबी का उपयोग कर रहा हूँ।

+0

एक रेगेक्स एक समय में एक ही सबस्ट्रिंग से मेल खाता है। एक regex लूप कैसे होस्टिंग भाषा की एक विशेषता है। आप किस भाषा का उपयोग कर रहे हैं? – tripleee

+0

@ ट्रिपली रूबी। –

उत्तर

13

उद्धरण मान लिया जाये कि सही ढंग से संतुलित हैं और फिर यह आसान है कोई उद्धरण भाग निकले देखते हैं,:

result = subject.gsub(/a(?=(?:[^"]*"[^"]*")*[^"]*\Z)/, '') 

यह रिक्त स्ट्रिंग के साथ सभी a रों बदल दे और तभी की समान संख्या है मिलान a से आगे उद्धरण।

स्पष्टीकरण: उद्धरण भीतर

a  # Match a 
(?=  # only if it's followed by... 
(?:  # ...the following: 
    [^"]*" # any number of non-quotes, followed by one quote 
    [^"]*" # the same again, ensuring an even number 
)*  # any number of times (0, 2, 4 etc. quotes) 
[^"]* # followed by only non-quotes until 
\Z  # the end of the string. 
)  # End of lookahead assertion 

आप बच गए कर सकते हैं उद्धरण (a "length: 2\""), यह अभी भी संभव है, लेकिन और अधिक जटिल हो जाएगा:

result = subject.gsub(/a(?=(?:(?:\\.|[^"\\])*"(?:\\.|[^"\\])*")*(?:\\.|[^"\\])*\Z)/, '') 

यह सार एक ही regex में है उपर्युक्त के रूप में, केवल को [^"] के लिए प्रतिस्थापित कर रहा है:

(?:  # Match either... 
\\. # an escaped character 
|  # or 
[^"\\] # any character except backslash or quote 
)  # End of alternation 
+0

+1 यह उत्तर –

+0

वाह है, एक प्रभावशाली नियमित अभिव्यक्ति! मुझे थोड़ी देर लग गई, लेकिन अब मैं समझता हूं कि यह कैसे काम करता है। :) डाउनवोट क्यों? –

0

प्रदर्शन या कोड-पठनीयता के बारे में देखभाल किए बिना, रेगेक्स प्रेमी के लिए पूर्ण उड़ा हुआ रेगेक्स समाधान।

यह समाधान मानता है कि कोई भागने वाला वाक्यविन्यास नहीं है (सिंटैक्स से बचने के साथ, a"sbd\"a" में स्ट्रिंग के अंदर गिना जाता है)।

स्यूडोकोड:

processedString = 
    inputString.replaceAll("\\".*?\\"","") // Remove all quoted strings 
       .replaceFirst("\\".*", "") // Consider text after lonely quote as inside quote 

तो फिर तुम पाठ आप processedString में चाहते मिलान कर सकते हैं। यदि आप बाहरी उद्धरण के रूप में अकेले उद्धरण के बाद टेक्स्ट मानते हैं तो आप दूसरी प्रतिस्थापन को हटा सकते हैं।

संपादित

रूबी में, कोड में regex ऊपर होगा

/\".*?\"/ 

gsub

और

/\".*/ 

के साथ प्रयोग किया sub


के साथ प्रयोग किया प्रतिस्थापन समस्या का समाधान करने के लिए, मुझे यकीन है कि क्या यह संभव है नहीं कर रहा हूँ, लेकिन यह कोशिश कर Worths:

  • एक काउंटर
  • gsub साथ regex /(\"|a)/ उपयोग घोषित, और आपूर्ति समारोह।
  • फ़ंक्शन में, यदि मैच " है, तो काउंटर वृद्धि करें, और प्रतिस्थापन के रूप में " वापस करें (मूल रूप से, कोई परिवर्तन नहीं)। यदि मैच a जांचता है कि काउंटर भी है या नहीं: यदि आपकी प्रतिस्थापन स्ट्रिंग भी प्रदान की जाती है; अन्यथा, जो भी मिलान किया गया है आपूर्ति करें।
+0

क्या ओपी आवश्यकता में उल्लिखित ए के साथ इसका कोई संबंध नहीं है? –

+0

@ElRonnoco: हाँ। एक बार में सब कुछ करने के बजाय, मैं बस सभी उद्धृत स्ट्रिंग को हटा देता हूं, और 'processedString' में केवल unquoted भागों को छोड़ देता हूं। फिर पाठ की खोज करना आसान होगा। हालांकि, मेरे समाधान में धारणा है। – nhahtdh

+0

आह, यह विचार है कि * फिर * आप 'a' के प्रतिस्थापन करते हैं ... –

4

जेएस-कोडर, इस प्राचीन प्रश्न को पुनर्जीवित कर रहा है क्योंकि इसका एक सरल समाधान था जिसका उल्लेख नहीं किया गया था। (अपने प्रश्न मिले, जबकि एक regex bounty quest के लिए कुछ शोध कर।)

आप देख सकते हैं regex स्वीकार किए जाते हैं जवाब में regex के साथ तुलना में वास्तव में छोटा है: ("[^"]*")|a

subject = 'a b c a b " a b " b a " a "' 
regex = /("[^"]*")|a/ 
replaced = subject.gsub(regex) {|m|$1} 
puts replaced 

इस live demo

देखें संदर्भ

How to match pattern except in situations s1, s2, s3

How to match a pattern unless...

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