2012-04-25 22 views
6

मुझे पता है कि मेरे पास ऐसे प्रश्न हैं जिनके उत्तर दिए गए हैं, लेकिन उनके माध्यम से पढ़ने के बाद भी मेरे पास अभी भी समाधान नहीं है जिसे मैं ढूंढ रहा हूं।पाइथन में नियमित अभिव्यक्तियों के साथ मिलान तिथियां?

पायथन 3.2.2 का उपयोग करके, मुझे "महीना, दिन, वर्ष" मैच करना होगा, जिसमें महीना एक स्ट्रिंग है, दिन दो अंक, 30, 31, या 28 फरवरी के लिए और 2 9 फरवरी के लिए एक लीप वर्ष पर ।

pattern = "(January|February|March|April|May|June|July|August|September|October|November|December)[,][ ](0[1-9]|[12][0-9]|3[01])[,][ ]((19|20)[0-9][0-9])" 
expression = re.compile(pattern) 
matches = expression.findall(sampleTextFile) 

मैं अभी भी regex वाक्य रचना के साथ भी परिचित नहीं कर रहा हूँ तो मैं वहाँ में अक्षर हैं जो अनावश्यक हैं ([हो सकता है: (मूल रूप से एक असली और मान्य दिनांक)

यह वही है मैं अब तक किया है ,] [] कॉमा और रिक्त स्थान के लिए इसके बारे में गलत तरीके से लगता है), लेकिन जब मैं अपनी नमूना पाठ फ़ाइल में "जनवरी, 26, 1 99 1" से मेल खाने का प्रयास करता हूं, तो "मैचों" में आइटमों का प्रिंटिंग होता है ('जनवरी', '26', '1 99 1', '1 9')।

अतिरिक्त '1 9' अंत में क्यों दिखाई देता है?

इसके अलावा, मैं अपने रेगेक्स में क्या चीजें जोड़ या बदल सकता हूं जो मुझे तारीखों को सही तरीके से सत्यापित करने की अनुमति देगी? मेरी योजना अभी लगभग सभी तिथियों को स्वीकार करना है और महीने और वर्ष समूह के साथ दिन समूह की तुलना करके उच्च स्तर की संरचनाओं का उपयोग करके उन्हें बाहर निकालना है, यह देखने के लिए कि दिन < 31,30,29,28

कोई भी मेरी रेगेक्स को डिजाइन करने के तरीके के बारे में रचनात्मक आलोचना सहित सहायता की बहुत सराहना की जाएगी।

+5

आपको नियमित अभिव्यक्ति का उपयोग करने की आवश्यकता क्यों है? (अब आपके पास दो समस्याएं हैं ...) – geoffspear

+0

मेरा मानना ​​है कि उद्धरण @Wooble का जिक्र है 'कुछ लोग, जब किसी समस्या का सामना करते हैं, तो सोचें "मुझे पता है, मैं नियमित अभिव्यक्तियों का उपयोग करूंगा।" अब उन्हें दो समस्याएं हैं। ' और मैं सहमत होने के इच्छुक हूं। मैं एक स्ट्रिंग और 2 संख्याओं को निकालने की अनुशंसा करता हूं (शायद एक साधारण, सरल रेगेक्स के साथ, लेकिन कॉमा पर स्ट्रिंग को विभाजित करके अधिक संभावना है) और फिर डेटाटाइम का उपयोग करके यह जांचने के लिए कि दिनांक वैध है या नहीं। –

+0

सलाह के लिए धन्यवाद, लेकिन यह एक होमवर्क असाइनमेंट है जहां मुझे मिलान तिथियों के लिए अभिव्यक्ति करने की आवश्यकता है। – ahabos

उत्तर

6

यहाँ एक रेगुलर एक्सप्रेशन अपने वांछित प्रारूप के किसी भी तारीख के अनुरूप होगा (हालांकि आप स्पष्ट रूप से, tweak कर सकता था कि अल्पविराम के वैकल्पिक हैं महीने के संक्षिप्त रूपों जोड़ने के लिए, और इतने पर) बनाने के लिए एक ही रास्ता है: तो फिर

years = r'((?:19|20)\d\d)' 
pattern = r'(%%s) +(%%s), *%s' % years 

thirties = pattern % (
    "September|April|June|November", 
    r'0?[1-9]|[12]\d|30') 

thirtyones = pattern % (
    "January|March|May|July|August|October|December", 
    r'0?[1-9]|[12]\d|3[01]') 

fours = '(?:%s)' % '|'.join('%02d' % x for x in range(4, 100, 4)) 

feb = r'(February) +(?:%s|%s)' % (
    r'(?:(0?[1-9]|1\d|2[0-8])), *%s' % years, # 1-28 any year 
    r'(?:(29), *((?:(?:19|20)%s)|2000))' % fours) # 29 leap years only 

result = '|'.join('(?:%s)' % x for x in (thirties, thirtyones, feb)) 
r = re.compile(result) 
print result 

हम है:

>>> r.match('January 30, 2001') is not None 
True 
>>> r.match('January 31, 2001') is not None 
True 
>>> r.match('January 32, 2001') is not None 
False 
>>> r.match('February 32, 2001') is not None 
False 
>>> r.match('February 29, 2001') is not None 
False 
>>> r.match('February 28, 2001') is not None 
True 
>>> r.match('February 29, 2000') is not None 
True 
>>> r.match('April 30, 1908') is not None 
True 
>>> r.match('April 31, 1908') is not None 
False 

और यह शानदार रेगेक्सप क्या है, आप पूछ सकते हैं?

>>> print result 
(?:(September|April|June|November) +(0?[1-9]|[12]\d|30), *((?:19|20)\d\d))|(?:(January|March|May|July|August|October|December) +(0?[1-9]|[12]\d|3[01]), *((?:19|20)\d\d))|(?:February +(?:(?:(0?[1-9]|1\d|2[0-8]), *((?:19|20)\d\d))|(?:(29), *((?:(?:19|20)(?:04|08|12|16|20|24|28|32|36|40|44|48|52|56|60|64|68|72|76|80|84|88|92|96))|2000)))) 

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

+0

इसके लिए धन्यवाद! मैं अभी भी रेगेक्सप के माध्यम से जा रहा हूं, आपने मुझे धीरे-धीरे अलग-अलग घटकों को समझने और समझने के लिए दिया है, लेकिन मैं देखता हूं कि ऐसा करने का सबसे अच्छा तरीका महीनों के साथ समूह करना होगा, मूल रूप से नाम के अलावा कोई मतभेद नहीं होगा और फरवरी से अलग शेष और मैच – ahabos

+0

अभिव्यक्ति के किसी अन्य भाग में मैंने कहा कि नियमित अभिव्यक्ति करने के लिए तिथि के खिलाफ महीने की जांच करने के लिए "कोई आसान तरीका नहीं" था। तो आपने दिखाया कि यह कैसे करें ... कठिन तरीका ... आप, महोदय, पागल हैं, लेकिन यह पागलपन की अच्छी तरह है। +1! अनुलेख मुझे विशेष रूप से लीप साल चेकर पसंद है। – steveha

+0

पैटर्न = आर '(% s) + (% s), *% s'% वर्ष मेरे लिए त्रुटि दिखा रहा है .. पैटर्न = '(% s) + (% s), *% s'% वर्ष टाइप एरर: प्रारूप स्ट्रिंग – monkey

1

अजगर time मॉड्यूल के हिस्से के रूप में एक तिथि पार्सर है:

import time 
time.strptime("December 31, 2012", "%B %d, %Y") 

ऊपर सभी दिनांक स्वरूप हमेशा एक ही है अगर आप की जरूरत है।

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

अब आपने कहा है कि टिप्पणियों में, यह होमवर्क है, मैं नियमित अभिव्यक्तियों पर सुझावों के साथ एक और उत्तर पोस्ट करूंगा।

सभी लोग जिन्होंने आपको बहुत अच्छी सलाह दे रहा है आप नियमित अभिव्यक्ति के अलावा कुछ का उपयोग का सुझाव दे रहा है:

+0

मुझे नियमित अभिव्यक्तियों का उपयोग करने की आवश्यकता है क्योंकि यह एक होमवर्क असाइनमेंट है, मैं – ahabos

+0

के साथ संघर्ष कर रहा हूं, यदि आपके पास एक स्ट्रिंग है जो सिर्फ तारीख है, लेकिन यह मेल करने के लिए 'regex' की तरह काम नहीं करती है, तो यह एक डेट ऑब्जेक्ट बनाता है एक स्ट्रिंग या बड़े पाठ में तिथियां। – Suz

2

यहाँ कुछ त्वरित विचार कर रहे हैं। दूसरी तरफ, नियमित अभिव्यक्ति वाक्यविन्यास के बारे में अधिक जानने के लिए हमेशा अच्छा समय होता है ...

वर्ग ब्रैकेट्स में एक अभिव्यक्ति - [...] - उन ब्रैकेट के अंदर किसी भी एकल वर्ण से मेल खाता है। तो [,] लिखना, जिसमें केवल एक ही वर्ण शामिल है, एक साधारण unadorned कॉमा लिखने के समान है: ,

.findall विधि स्ट्रिंग में सभी मिलान समूहों की एक सूची देता है। एक समूह को parenthese - (...) द्वारा पहचाना जाता है - और वे बाएं से दाएं, सबसे पहले सबसे पहले गिना जाता है। आपकी अंतिम अभिव्यक्ति इस तरह दिखता है:

((19|20)[0-9][0-9]) 

सबसे बाहरी कोष्ठक पूरे वर्ष से मेल खाते हैं, और अंदर कोष्ठक पहले दो अंक से मेल खाते हैं। इसलिए, "1 9 8 9" जैसी तारीख के लिए, अंतिम दो मैच समूह 1989 और 19 होने जा रहे हैं।

+2

गैर-मिलान करने वाले समूहों के बारे में उसे ठीक करने का तरीका बताएं। (?: 1 9 | 20) – ricochet1k

+0

नहीं, मैं आपको ऐसा करने दूँगा। मुझे सच में यकीन नहीं है कि इसे "फिक्सिंग" की आवश्यकता है, क्योंकि कुछ भी "टूटा हुआ" नहीं है। मैं बस व्यवहार की व्याख्या करना चाहता था। – larsks

2

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

((19|20)[0-9][0-9])

सबसे बाहरी कोष्ठक पूरे वर्ष से मेल खाते हैं, और अंदर कोष्ठक पहले दो अंक से मेल खाते हैं। इसलिए, "1 9 8 9" जैसी तारीख के लिए, दो मैच समूह 1 9 8 9 और 1 9 होने जा रहे हैं। चूंकि आप आंतरिक समूह (पहले दो अंक) नहीं चाहते हैं, तो आपको इसके बजाय एक गैर-कैप्चरिंग समूह का उपयोग करना चाहिए। गैर-कैप्चरिंग समूह ?: से शुरू होते हैं, इस तरह प्रयोग किया जाता है: (?:a|b|c)

वैसे, नियमित अभिव्यक्ति here का उपयोग करने के तरीके पर कुछ अच्छे दस्तावेज हैं।

0

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

((19|20)[0-9][0-9]) 

यहाँ आपकी समस्या है, regex के आधार पर पूरे वर्ष और 19 या 20 दोनों का मिलान करेगा कि क्या के साथ 19 या 20

+0

आपके ब्रांड्स असंतुलित हैं। – ricochet1k

+0

धन्यवाद उसे नहीं देखा। – danielz

1

आप इस नियमित अभिव्यक्ति है साल शुरू:

pattern = "(January|February|March|April|May|June|July|August|September|October|November|December)[,][ ](0[1-9]|[12][0-9]|3[01])[,][ ]((19|20)[0-9][0-9])" 

नियमित अभिव्यक्तियों की एक विशेषता एक "चरित्र वर्ग" है। वर्ग ब्रैकेट में वर्ण एक चरित्र वर्ग बनाते हैं। इस प्रकार [,] एक वर्ण वर्ग, , (एक अल्पविराम) से मेल खाने वाला एक वर्ण वर्ग है। आप बस अल्पविराम भी डाल सकते हैं।

शायद आप अल्पविराम को वैकल्पिक बनाना चाहते थे? इसके बाद आप एक प्रश्न चिह्न डाल कर ऐसा कर सकते हैं: ,?

जो कुछ भी आप कोष्ठक में डालते हैं वह "मैच समूह" बनाता है। मुझे लगता है कि रहस्यमय अतिरिक्त "1 9" एक मैच समूह से आया था जिसका मतलब आपके पास नहीं था। उदाहरण के लिए (?:

तो,:: आप एक मेल नहीं खाने वाले समूह इस सिंटैक्स का उपयोग कर सकते हैं

r'(?:red|blue) socks' 

इस 'लाल मोज़ों "या" नीले मोजे "से मेल होगा, लेकिन एक मैच समूह नहीं है। आप तो डाल कि सादा कोष्ठकों के अंदर हैं:

r'((?:red|blue) socks)' 

कि एक मैच समूह, जिसका मूल्य होगा "red socks" या "blue socks"

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

महीने के मुकाबले तारीख को सत्यापित करने के लिए, यह नियमित अभिव्यक्ति के दायरे से बाहर है। आपका पैटर्न "February 31" से मेल खाता है और इसे ठीक करने का कोई आसान तरीका नहीं है।

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