2011-07-26 18 views
9

में अंकगणितीय परिचालन मैं जीएडिट रेगेक्स प्लगइन (पायथन शैली regex) का उपयोग कर रहा हूँ। मैं समूह में बैकरेफर पर कुछ अंकगणितीय ऑपरेशन करना चाहता हूं।रेगेक्स

उदाहरण के लिए:

PART 1 DATA MODELS Chapter 
2 Entity-Relationship Model 27 

मैं इसे बदलना चाहते हैं

PART 1 DATA MODELS Chapter 25 
2 Entity-Relationship Model 27 

मेरे regex ^(PART.*)\n(.*\s(\d+))\n है होना करने के लिए, और मैं \1 (\3-2)\n\2\n की तरह कुछ जहां \3-2 करने के लिए है के साथ बदलना चाहते हैं बैकरेफर \3 शून्य 2 हो। लेकिन प्रतिस्थापन रेगेक्स सही नहीं है। मुझे आश्चर्य है कि यह कैसे करें? धन्यवाद!

+0

जादू हार्डकोडेड 2 कहां से आया, क्या यह दूसरी पंक्ति की शुरुआत से बीवी रेगेक्स से मेल खाता था? – smci

+0

रिकॉर्ड के लिए, मैं यह इंगित करना चाहता हूं कि इस तरह की सुविधा एक संभावित सुरक्षा जोखिम होगी। सबसे पहले यह गणित है, तो कोई फंक्शंस चाहता है, फिर ट्रिगर या जो भी हो, और आखिर में कोई स्टैक ओवरफ्लो शोषण या कुछ बताता है। तो सावधान रहें कि आप क्या चाहते हैं। –

+0

सुरक्षा जोखिम? किसी दुर्भावनापूर्ण चल रहे जीएडिट से? मुझे ऐसा नहीं लगता। यदि वे पहले ही जीएडिट कर रहे हैं, तो वे पहले से ही कुछ भी कर सकते हैं जो सुडो के बिना किया जा सकता है। – Phob

उत्तर

3

मुझे पता नहीं है कि आप गणित में गणित या अन्य गणना कर सकते हैं। अगर वहां एक रेगेक्स इंजन है जो इसका समर्थन करता है, तो यह वास्तव में निफ्टी होगा! लेकिन मेरी समझ यह है कि रेगेक्स इंजन को अत्यधिक धीमा किए बिना व्यावहारिक नहीं होगा।

मुझे लगता है कि आपका सर्वश्रेष्ठ दांव sub regex समारोह/विधि का उपयोग करने होगा:

re.sub(pattern, repl, string[, count, flags]) 

वापसी स्ट्रिंग प्रतिस्थापन द्वारा स्ट्रिंग में पैटर्न के सबसे बाईं ओर गैर-अतिव्यापी घटनाओं की जगह द्वारा प्राप्त repl। यदि पैटर्न नहीं मिला है, स्ट्रिंग अपरिवर्तित लौटा दी गई है। प्रतिलिपि एक स्ट्रिंग या एक समारोह हो सकता है; यदि यह एक स्ट्रिंग है, तो इसमें बैकस्लैश से बचने के लिए संसाधित किया जाता है। यही है, \ n को एक एकल न्यूलाइन वर्ण में परिवर्तित किया गया है, \ r को लाइनफीड में परिवर्तित किया गया है, और बहुत आगे। अज्ञात भागने जैसे \ j अकेले रह गए हैं। बैक्रेरेंस, जैसे कि \ 6, को पैटर्न में समूह 6 द्वारा मिलान किए गए सबस्ट्रिंग के साथ प्रतिस्थापित किया गया है। उदाहरण के लिए:

>>> re.sub(r'def\s+([a-zA-Z_][a-zA-Z_0-9]*)\s*\(\s*\):', 
...  r'static PyObject*\npy_\1(void)\n{', 
...  'def myfunc():') 
'static PyObject*\npy_myfunc(void)\n{' 

तो repl एक समारोह है, यह पैटर्न के हर गैर-अतिव्यापी घटना के लिए कहा जाता है। फ़ंक्शन एक एकल मिलान ऑब्जेक्ट तर्क लेता है, और प्रतिस्थापन स्ट्रिंग देता है। उदाहरण के लिए:

>>> def dashrepl(matchobj): 
...  if matchobj.group(0) == '-': return ' ' 
...  else: return '-' 
>>> re.sub('-{1,2}', dashrepl, 'pro----gram-files') 
'pro--gram files' 
>>> re.sub(r'\sAND\s', ' & ', 'Baked Beans And Spam', flags=re.IGNORECASE) 
'Baked Beans & Spam' 

पैटर्न एक स्ट्रिंग या एक आरई वस्तु हो सकता है।

वैकल्पिक तर्क गणना पैटर्न की अधिकतम संख्या प्रतिस्थापित करने के लिए है; गिनती एक गैर-ऋणात्मक पूर्णांक होना चाहिए। यदि छोड़े गए या शून्य, सभी घटनाओं को प्रतिस्थापित कर दिया जाएगा। के लिए खाली मिलान केवल पैटर्न को प्रतिस्थापित किया जाता है जब पिछले मैच के निकट नहीं, तो उप ('x *', '-', 'abc') '-a-b-c-' देता है।

ऊपर वर्णित वर्णित चरित्र से बचने और बैकरेरेंस के अतिरिक्त, \ g नाम वाले समूह द्वारा मिलान किए गए सबस्ट्रिंग का उपयोग करेगा, जैसा कि (? पी ...) वाक्यविन्यास द्वारा परिभाषित किया गया है। \ g संबंधित समूह संख्या का उपयोग करता है; \ g < 2> इसलिए \ 2 के बराबर है, लेकिन \ g < 2> 0 जैसे प्रतिस्थापन में संदिग्ध नहीं है। \ 20 समूह 20 के संदर्भ के रूप में व्याख्या किया जाएगा, समूह 2 के संदर्भ में शाब्दिक चरित्र '0' के संदर्भ में नहीं होगा।आरई द्वारा मिलान किए गए पूरे सबस्ट्रिंग में बैकरेफर \ g < 0> विकल्प।

आप एक समारोह है कि मूल्यों की गणना करता है मूल स्ट्रिंग में वापस स्थानापन्न के रूप में repl पारित कर सकते हैं।

+0

यदि प्रतिस्थापन ऑपरेशन के हिस्से के रूप में अंकगणित पोस्ट-मैच किया जाता है, तो यह संभव हो सकता है। लेकिन हाँ, एक खोज के दौरान अंकगणित तब तक धीमा हो जाएगा जब तक regexs वर्चुअल मशीन या कुछ को संकलित नहीं कर सकता ... ow। –

1

जब तक जीएडिट पाइथन का सुपरसैट नहीं है, तो यह (\3-2) के साथ करने की कोशिश कर रहा है, यह एक प्रतिस्थापन-रेगेक्स के अंदर संचालन की अनुमति नहीं देगा। किसी भी मामले में, \3 एक स्ट्रिंग है और आपको पहले int() के साथ कनवर्ट करना होगा। तो आपको इसे अलग re.search (...) में तोड़ना होगा, डाले गए पगेनो की गणना करें, फिर सम्मिलित करें।

दूसरा मुद्दा यह है कि आप '2' के पेजलेथेंथ से मेल नहीं खाते हैं, आपने इसे हार्डकोड किया है = - क्या आप चाहते हैं कि आपका रेगेक्स दूसरी पंक्ति की शुरुआत से मेल खाता हो?

(इसके अलावा किसी भी मामले में अपने बहु मैच केवल, भाग के बाद एक लाइन से मेल खाते हैं, तो आप क्या इरादा है कि होगा।)

यहाँ यह सादे पायथन regex में कार्यान्वित किया जाता:

for (chap,sect,page) in re.finditer(r'^(PART.*)\n(.*\s+(\d+))\n', input, re.M): 
    print chap, int(page)-2 
    print sect 

(मैं रैप करने के लिए है कि एक repl fn paginate_chapter(matchobj) के रूप में, re.sub मज़बूती से अभी तक कॉल करने के लिए है कि नहीं मिल सकता है ...)

5

निम्नलिखित कोड क्या आप स्ट्रिंग आप उदाहरण के रूप में दिया था पर चाहते हैं करता है की कोशिश की। एक बिंदु यह है कि यह इस स्ट्रिंग के प्रारूप के लिए विशिष्ट है, यह तारों की विविधता का प्रबंधन नहीं कर सकता है: क्या यह वास्तव में केवल स्ट्रिंग के इस प्रारूप तक ही सीमित है?

import re 

ss = '''PART 1 DATA MODELS Chapter 
2 Entity-Relationship Model 27 

The sun is shining 

PART 1 DATA MODELS Chapter 
13 Entity-Relationship Model 45 
''' 

regx = re.compile('^(PART.*)(\n(\d*).*\s(\d+)\n)',re.MULTILINE) 

def repl(mat): 
    return ''.join((mat.group(1),' ', 
        str(int(mat.group(4))-int(mat.group(3))), 
        mat.group(2))) 

for mat in regx.finditer(ss): 
    print mat.groups() 

print 

print regx.sub(repl,ss) 

परिणाम

('PART 1 DATA MODELS Chapter', '\n2 Entity-Relationship Model 27\n', '2', '27') 
('PART 1 DATA MODELS Chapter', '\n13 Entity-Relationship Model 45\n', '13', '45') 

PART 1 DATA MODELS Chapter 25 
2 Entity-Relationship Model 27 

The sun is shining 

PART 1 DATA MODELS Chapter 32 
13 Entity-Relationship Model 45 

संपादित: मैं re.MULTILINE झंडा

7

आप re.sub लैम्ब्डा समारोह है जो हर गैर-अतिव्यापी पैटर्न मैच के लिए re.MatchObject वस्तु लेता है पारित कर सकते हैं भूल गया था और रिटर्न प्रतिस्थापन स्ट्रिंग। उदाहरण के लिए:

import re  
print re.sub("(\d+)\+(\d+)", 
      lambda m: str(int(m.group(1))+int(m.group(2))), 
      "If 2+2 is 4 then 1+2+3+4 is 10") 

प्रिंट

तो 4 4 है तो 3 + 7 आप आसानी से आपकी समस्या का यह लागू हो सकते हैं 10

है।

+0

ग्रेट उत्तर, मुझे लगता है कि यह स्वीकार किया जाना चाहिए –

+0

यह उत्तर शानदार है। धन्यवाद! – Avision