2012-12-31 7 views
9

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

(नोट:। मैं अजगर का उपयोग कर रहा है, लेकिन इस में कोई फर्क नहीं होना चाहिए):

s = "foo\nbar\nfood\nfoo" 

मैं बस एक regex कि मिलान कर देंगे खोजने की कोशिश कर रहा हूँ

मैं निम्नलिखित स्ट्रिंग है कहो "फू" के दोनों उदाहरण, लेकिन "भोजन" नहीं, इस तथ्य के आधार पर कि "भोजन" में "foo" तुरंत या तो नई लाइन या स्ट्रिंग के अंत के बाद नहीं होता है।

यह शायद मेरे प्रश्न को व्यक्त करने का एक अत्यधिक जटिल तरीका है, लेकिन यह काम करने के लिए कुछ ठोस बनाता है। परिणाम के साथ (नोट: परिणाम मैं चाहता हूं [foo\n, foo] है):

यहाँ, बातें मैं कोशिश की है में से कुछ हैं

foo[\n\Z] => ['foo\n']

foo(\n\Z) => ['\n' , ''] < = यह न्यू लाइन और EOS मैच के लिए लगता है, लेकिन नहीं foo

foo($|\n) => ['\n', '']

(foo)($|\n) => [(foo, '\n'), (foo, '')] < = लगभग हो गया है, और यह एक उपयोगी योजना बी है, लेकिन मैं सही समाधान खोजने के लिए चाहते हैं।

केवल एक चीज मैंने पाया कि काम करता है:

foo$|foo\n => ['foo\n', ` 'foo']

इस तरह के एक सरल उदाहरण के लिए ठीक है, लेकिन यह कैसे यह देखना आसान है एक बहुत बड़ी अभिव्यक्ति के साथ अनावश्यक हो सकता है (और हाँ, यह foo चीज वास्तव में उपयोग की जा रही बड़ी अभिव्यक्ति के लिए एक स्टैंड है)।


अलग दिलचस्प:, मैं बस स्थानापन्न सकता है मेरी 'विशिष्ट चरित्र' के लिए \nIn regex, match either the end of the string or a specific character

यहाँ: निकटतम तो सवाल मैं अपने समस्या के लिए मिल सकता है इस से एक था। अब, स्वीकृत उत्तर regex /(&|\?)list=.*?(&|$)/ का उपयोग करता है। मैंने देखा कि ओपी जावास्क्रिप्ट का उपयोग कर रहा था (प्रश्न javascript टैग के साथ टैग किया गया था), इसलिए शायद जावास्क्रिप्ट रीगेक्स दुभाषिया अलग है, लेकिन जब मैं पाइथन में उपरोक्त रेगेक्स के साथ प्रश्न में दिए गए सटीक तारों का उपयोग करता हूं, तो मुझे खराब परिणाम मिलते हैं:

>>> findall("(&|\?)list=.*?(&|$)", "index.php?test=1&list=UL") 
[('&', '')] 
>>> findall("(&|\?)list=.*?(&|$)", "index.php?list=UL&more=1") 
[('?', '&')] 

तो, मैं स्टंप हो गया हूं।

+0

क्या आप [re.MULTILINE] (http://docs.python.org/2/library/re.html) के बारे में जानते हैं? –

+0

हां, और मुझे पता है कि यह मेरे लिए पायथन में काम करेगा, लेकिन मैं एक भाषा अज्ञेय समाधान ढूंढना चाहता हूं। –

उत्तर

7
>>> import re 
>>> re.findall(r'foo(?:$|\n)', "foo\nbar\nfood\nfoo") 
['foo\n', 'foo'] 

(?:...) एक non-capturing group बनाता है।

इसका कारण यह है (re module reference से) काम करता है:

re.findall (पैटर्न, स्ट्रिंग, झंडे = 0)

वापसी सभी गैर-अतिव्यापी स्ट्रिंग में पैटर्न के मिलान, स्ट्रिंग की एक सूची के रूप में । स्ट्रिंग को बाएं से दाएं स्कैन किया जाता है, और पाए गए क्रम में मैचों को वापस कर दिया जाता है। यदि पैटर्न में एक या अधिक समूह मौजूद हैं, तो समूह की एक सूची लौटाएं; यदि पैटर्न में एक से अधिक समूह हैं तो यह tuples की एक सूची होगी। रिक्त मिलान परिणाम में शामिल नहीं किए जाते हैं जब तक कि वे किसी अन्य मैच की शुरुआत को स्पर्श न करें।

+0

हू। ऐसा क्यों है कि मानक समूह के बजाय गैर-कैप्चरिंग समूह का उपयोग करना? क्यों पुराना पुराना 'r'foo ($ | \ n)' 'वही काम नहीं करता है? –

+0

इसके अलावा, यह वही है जो मैं चाहता था। बहुत बहुत धन्यवाद! –

+1

यदि आपके पास सामान्य समूह में '$ | \ n' है, तो आप लाइन ब्रेक से मिलान करेंगे (और केवल मिलान करेंगे) (जैसा कि कैप्चरिंग समूह में कुछ भी नहीं है)। आप foo को एक समूह में भी डाल सकते हैं, लेकिन फिर आप फिर से लाइन ब्रेक के लिए अतिरिक्त समूह परिणामों के साथ समाप्त हो जाएंगे। – poke

1

आप केवल foo के साथ संबंध रहे हैं: केवल शुरुआत या अंत में

\b

रिक्त स्ट्रिंग से मेल खाता है, लेकिन:

In [42]: import re 

In [43]: strs="foo\nbar\nfood\nfoo" 

In [44]: re.findall(r'\bfoo\b',strs) 
Out[44]: ['foo', 'foo'] 

\b है एक शब्द सीमा को दर्शाता है एक शब्द का एक शब्द को अल्फान्यूमेरिक या अंडरस्कोर वर्णों के अनुक्रम के रूप में परिभाषित किया जाता है, इसलिए किसी शब्द का अंत व्हाइटस्पेस या गैर-अल्फान्यूमेरिक, गैर-अंडरस्कोर वर्ण द्वारा इंगित किया जाता है। ध्यान दें कि औपचारिक रूप से, \ ख w एक \ w और एक \ डब्ल्यू चरित्र (या इसके विपरीत) के बीच की सीमा के रूप में परिभाषित, या \ के बीच और स्ट्रिंग की शुरुआत/अंत है, तो यह समझा पात्रों में से सटीक सेट है अल्फान्यूमेरिक UNICODE और LOCALE झंडे के मानों पर निर्भर करता है। उदाहरण के लिए, आर '\ bfoo \ b' मैचों 'foo', 'foo।', '(Foo)', 'bar foo baz' लेकिन 'foobar' या 'foo3' नहीं। एक वर्ण श्रृंखला के अंदर, \ b पाइथन के स्ट्रिंग अक्षर के साथ संगतता के लिए बैकस्पेस वर्ण का प्रतिनिधित्व करता है।

(Source)

+0

यह समझा लायक हो सकता है [ '\ b'] (http://docs.python.org/2/library/re.html#regular-expression-syntax)। (में संपादित) –

+0

फिर, 'foo' एक और अधिक जटिल अभिव्यक्ति के लिए सिर्फ एक प्लेसहोल्डर है। मैं वास्तव में क्या देख रहा हूं कि लाइन के अंत या स्ट्रिंग के अंत के खिलाफ कैसे जांचें। कई मामलों में, शब्द सीमाओं की जांच के लिए '\ b' का उपयोग करके अभिव्यक्ति तोड़ सकती है। हालांकि अच्छा विचार है। यह अपनी आवश्यकताओं का अनुमान लगाना एक तरह से मुश्किल है अगर तुम उन्हें नहीं दिखा - –

+2

@KenB वास्तव में पता चलता है कि आप क्या चाहते हैं उदाहरण दे। –

2

आप re.MULTILINE का उपयोग करें और अपने पैटर्न में $ के बाद एक वैकल्पिक LINEBREAK शामिल हो सकते हैं:

s = "foo\nbar\nfood\nfoo" 
pattern = re.compile('foo$\n?', re.MULTILINE) 
print re.findall(pattern, s) 
# -> ['foo\n', 'foo'] 
+0

मुझे यह पसंद है, लेकिन मैं वास्तव में एक भाषा अज्ञेयवादी समाधान खोजना पसंद करूंगा। चूंकि 'पुनः। मल्टीलाइन' पाइथन विशिष्ट है, इसलिए मैं अन्य भाषाओं में भविष्य के उपयोग के लिए इसे टालना चाहता हूं। –

+3

अधिकांश नियमित अभिव्यक्ति इंजन एक मल्टीलाइन विकल्प का समर्थन करते हैं। आप इसे सीधे पैटर्न में भी एम्बेड कर सकते हैं: 're.findall (' (? M) foo $ \ n? ', एस) '। – omz

+1

@ केएनबी वास्तव में, मल्टीलाइन की तरह झंडे पायथन विशिष्ट नहीं हैं, उनके पास अन्य भाषाओं पर अलग वाक्यविन्यास है (उदाहरण के लिए पर्ल 'मल्टीलाइन' में '$ s = ~/blah/m' या कुछ होगा)। मुझे कभी एहसास नहीं हुआ कि ध्वज पैटर्न में शामिल किया जा सकता है, यह जानना वास्तव में उपयोगी है, धन्यवाद! : डी – dbr

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