2008-09-26 12 views
7

मुझे चरित्र (कहें) x चरित्र (कहें) पी स्ट्रिंग में प्रतिस्थापित करने की आवश्यकता है, लेकिन केवल तभी जब यह उद्धृत सबस्ट्रिंग में निहित है।क्या इस विशेष स्ट्रिंग मैनिपुलेशन के लिए रेगेक्स का उपयोग किया जा सकता है?

axbx'cxdxe'fxgh'ixj'k -> axbx'cPdPe'fxgh'iPj'k 

के मान लेते हैं, सरलता के, कि हमेशा जोड़े में आ उद्धरण: एक उदाहरण यह स्पष्ट कर देता है।

स्पष्ट तरीका केवल एक समय में स्ट्रिंग एक वर्ण को संसाधित करना है (एक साधारण राज्य मशीन दृष्टिकोण);
हालांकि, मैं सोच रहा हूं कि नियमित रूप से अभिव्यक्तियों का उपयोग एक ही समय में सभी प्रसंस्करण करने के लिए किया जा सकता है।

मेरी लक्षित भाषा सी # है, लेकिन मुझे लगता है कि मेरा प्रश्न नियमित अभिव्यक्तियों के लिए अंतर्निहित या लाइब्रेरी समर्थन वाली किसी भी भाषा से संबंधित है।

+0

निकालें 'नियमित-भाव' टैग –

उत्तर

8

मैं अजगर के साथ ऐसा करने में सक्षम था चरित्र एक्स उद्धृत स्ट्रिंग के भीतर है। यह अगले उद्धरण तक कुछ गैर-पात्र पात्रों की तलाश करता है, फिर स्ट्रिंग के अंत तक, एकल अक्षरों या वर्णों के उद्धृत समूहों का अनुक्रम दिखता है।

यह आपकी धारणा पर निर्भर करता है कि उद्धरण हमेशा संतुलित होते हैं। यह भी बहुत कुशल नहीं है।

+0

भी विचार करें कि यह re.sub है में 'एक्स' की जगह 'पी' द्वारा खोजें) फ़ंक्शन जो स्ट्रिंग पर पुनरावृत्त होता है। नियमित अभिव्यक्ति स्वयं केवल उद्धरण के भीतर पहले एक्स से मेल खाती है। –

+0

मैं कल्पना नहीं कर सकता कि आप re.sub() जैसी कुछ चीज़ों के बिना इस समस्या के समाधान का भी प्रतिनिधित्व कैसे करेंगे। आखिरकार, नियमित रूप से एक नियमित अभिव्यक्ति केवल मेल खाती है, और मूल प्रश्न को बदलने के बारे में पूछा जाता है। –

+0

आप सही हैं: इसे कुछ "अतिरिक्त मशीनरी" को समझ नहीं लिया जा सकता है, यही कारण है कि कई ने जवाब दिया कि "सादा नियमित अभिव्यक्ति" जहां पर्याप्त शक्तिशाली नहीं है –

1

सादे regexp के साथ नहीं। नियमित अभिव्यक्तियों में "स्मृति" नहीं होती है, इसलिए वे "अंदर" या "बाहरी" उद्धरण के बीच अंतर नहीं कर सकते हैं।

आप gema का उपयोग कर इसे straighforward होगा उदाहरण के लिए और अधिक शक्तिशाली कुछ चाहिए,:

'<repl>'=$0 
repl:x=P 
0

अपनी आशाओं को तोड़ने के लिए क्षमा करें, लेकिन आप एक धक्का-डाउन ऑटोमेटा की जरूरत है कि क्या करना है। Pushdown Automaton

छोटा है, रेगुलर एक्सप्रेशन वे जो परिमित अवस्था की मशीनों केवल पढ़ सकते हैं और जबकि पुशडाउन automaton एक ढेर और जोड़ तोड़ की क्षमता है कोई स्मृति है सकते हैं: वहाँ अधिक जानकारी है।

संपादित करें:

>>> import re 
>>> re.sub(r"x(?=[^']*'([^']|'[^']*')*$)", "P", "axbx'cxdxe'fxgh'ixj'k") 
"axbx'cPdPe'fxgh'iPj'k" 

यह क्या करता है कि जाँच करने के लिए गैर-कैप्चरिंग मैच (? = ...) का उपयोग है: वर्तनी ...

1

संतुलित पाठ के बारे में इसी प्रकार के विचार-विमर्श की जगह: Can regular expressions be used to match nested patterns?

यद्यपि आप विम में यह कोशिश कर सकते हैं, लेकिन यह काम करता है अच्छी तरह से ही अगर स्ट्रिंग एक लाइन पर है, और वहाँ के का केवल एक जोड़ी है।

:%s:\('[^']*\)x\([^']*'\):\1P\2:gci 

यदि कोई और जोड़ी या यहां तक ​​कि असंतुलित है, तो यह असफल हो सकता है। इस तरह मैंने c a.k.a. ex कमांड पर ध्वज की पुष्टि की है।

यह बिना किसी बातचीत के, sed के साथ किया जा सकता है - या awk के साथ ताकि आप कुछ बातचीत जोड़ सकें।

' के जोड़े पर लाइनों को तोड़ने का एक संभावित समाधान है तो आप विम समाधान के साथ कर सकते हैं।

+0

मुझे लगता है कि यह केवल उद्धरण के अंदर पाए गए पहले एक्स को प्रतिस्थापित करेगा। बाद के एक्स का मिलान गैर-एस्ट्रोफ़े पैटर्न [^ '] * – jop

+0

से किया जाएगा आप सही हैं। लेकिन इसे सभी एक्स की जगह बदलने के लिए संशोधित किया जा सकता है। –

+0

http://stackoverflow.com/questions/138552?sort=votes#138615 में टिप्पणियां देखें – jop

9

मैंने ग्रेग हेगिल के पायथन कोड को सी # में परिवर्तित कर दिया और यह काम किया!

[Test] 
public void ReplaceTextInQuotes() 
{ 
    Assert.AreEqual("axbx'cPdPe'fxgh'iPj'k", 
    Regex.Replace("axbx'cxdxe'fxgh'ixj'k", 
     @"x(?=[^']*'([^']|'[^']*')*$)", "P")); 
} 

वह परीक्षण पास हो गया।

1
Pattern:  (?s)\G((?:^[^']*'|(?<=.))(?:'[^']*'|[^'x]+)*+)x 
Replacement: \1P 
  1. \G — एंकर पिछले एक, या स्ट्रिंग की शुरुआत के अंत में प्रत्येक मैच।
  2. (?:^[^']*'|(?<=.)) — यदि यह स्ट्रिंग की शुरुआत में है, तो पहले उद्धरण तक मेल करें।
  3. (?:'[^']*'|[^'x]+)*+ — बिना किसी वर्णित वर्णों के किसी भी ब्लॉक, या किसी भी (गैर-उद्धरण) वर्णों को 'x' तक मिलान करें।

एक स्वीप एक सिंगल कैरेक्टर लुक-बैक को छोड़कर, स्रोत स्ट्रिंग को खराब करता है।

2

चाल स्ट्रिंग का हिस्सा निम्नलिखित मैच (चरित्र एक्स) हम खोज रहे हैं मैच के लिए गैर-कैप्चरिंग समूह का प्रयोग है। x तक स्ट्रिंग से मिलान करने का प्रयास करने से पहले या तो अंतिम या आखिरी मौका मिलेगा, भले ही गैर-लालची क्वांटिफ़ायर का उपयोग किया जाए। यहां ग्रेग का विचार टीसीएल को टिप्पणियों के साथ स्थानांतरित किया गया है।

 
set strIn {axbx'cxdxe'fxgh'ixj'k} 
set regex {(?x)      # enable expanded syntax 
            # - allows comments, ignores whitespace 
      x      # the actual match 
      (?=      # non-matching group 
       [^']*'    # match to end of current quoted substring 
            ## 
            ## assuming quotes are in pairs, 
            ## make sure we actually were 
            ## inside a quoted substring 
            ## by making sure the rest of the string 
            ## is what we expect it to be 
            ## 
       (
        [^']*   # match any non-quoted substring 
        |    # ...or... 
        '[^']*'   # any quoted substring, including the quotes 
       )*     # any number of times 
       $     # until we run out of string :) 
      )      # end of non-matching group 
} 

#the same regular expression without the comments 
set regexCondensed {(?x)x(?=[^']*'([^']|'[^']*')*$)} 

set replRegex {P} 
set nMatches [regsub -all -- $regex $strIn $replRegex strOut] 
puts "$nMatches replacements. " 
if {$nMatches > 0} { 
    puts "Original: |$strIn|" 
    puts "Result: |$strOut|" 
} 
exit 

यह प्रिंट:

3 replacements. 
Original: |axbx'cxdxe'fxgh'ixj'k| 
Result: |axbx'cPdPe'fxgh'iPj'k| 
2
#!/usr/bin/perl -w 

use strict; 

# Break up the string. 
# The spliting uses quotes 
# as the delimiter. 
# Put every broken substring 
# into the @fields array. 

my @fields; 
while (<>) { 
    @fields = split /'/, $_; 
} 

# For every substring indexed with an odd 
# number, search for x and replace it 
# with P. 

my $count; 
my $end = $#fields; 
for ($count=0; $count < $end; $count++) { 
    if ($count % 2 == 1) { 
     $fields[$count] =~ s/a/P/g; 
    }  
} 

इस हिस्सा काम करना नहीं चाहेंगे?

2

एक अधिक सामान्य (और सरल) समाधान जो गैर-युग्मित उद्धरणों की अनुमति देता है।

  1. उद्धृत स्ट्रिंग (
  2. स्ट्रिंग

    #!/usr/bin/env python 
    import re 
    
    text = "axbx'cxdxe'fxgh'ixj'k" 
    
    s = re.sub("'.*?'", lambda m: re.sub("x", "P", m.group(0)), text) 
    
    print s == "axbx'cPdPe'fxgh'iPj'k", s 
    # -> True axbx'cPdPe'fxgh'iPj'k 
    
संबंधित मुद्दे

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