2008-10-29 15 views
23

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

अगर मैं की तरह कुछ है। ..

/((foo)|(bar))/ 

यह भरपाई कर देंगे "foobar"। मैं जो खोज रहा हूं वह नहीं तो, मैं केवल एक शब्द या दूसरा मौजूद होने पर रेगेक्स मैच कैसे बना सकता हूं?

धन्यवाद!

+0

कोई मिलान हो Foofoobar चाहेंगे क्योंकि यह शामिल है " foo "और" foobar "? "फूनबार" के बारे में कैसे?क्या आप मैचों और गैर-मैचों के उदाहरण प्रदान कर सकते हैं? –

+0

से मेल खाता है: "foo" "बार" nonmatches: "foofoo" "barfoo" "foobarfoo" "barbar" "barfoofoo" – SocialCensus

+2

आप "foofoo" मैच के लिए नहीं करना चाहते हैं, तो आप ' वास्तव में एक विशेष या के बारे में बात नहीं कर रहे हैं। – cjm

उत्तर

8

आप किसी एक regex के साथ ऐसा कर सकते हैं, लेकिन मैं पठनीयता के कारण सुझाव है कि आप कुछ पसंद है ...

(/foo/ and not /bar/) || (/bar/ and not /foo/) 
+0

दरअसल, मुझे पूरा यकीन है कि मैं एक्सओआर तर्क को कोड में ही डाल दूंगा, न कि regexp में। – Pistos

+1

या इससे भी बेहतर,/foo/xor/bar /, अगर आपकी भाषा में एक्सओआर ऑपरेटर है। (पर्ल करता है।) – cjm

+0

यह सबसे अच्छा समाधान प्रतीत होता है, धन्यवाद! – SocialCensus

0

मैं कुछ इस तरह का उपयोग करेंगे। यह सिर्फ शब्दों के चारों ओर स्थान के लिए जांच करता है, लेकिन यदि आप \w का उपयोग करते हैं तो आप सीमा के लिए \b या \B का उपयोग कर सकते हैं। यह "foo" या "bar" से मेल खाता है, इसलिए जाहिर है कि आपको व्हाइटस्पेस को भी बदलना होगा, बस मामले में। (मान लें कि आप कुछ भी बदल रहे हैं।)

/\s((foo)|(bar))\s/ 
0

मुझे नहीं लगता कि यह एक नियमित अभिव्यक्ति के साथ किया जा सकता है। और आप जो मेल खाते हैं उसके आधार पर सीमाएं काम कर सकती हैं या नहीं भी हो सकती हैं।

मैं प्रत्येक रेगेक्स के खिलाफ अलग से मेल खाता हूं, और परिणाम पर एक्सओआर करता हूं। अगर मैं g विकल्प को चेक

x foo y 
x bar y 
x foobar y 

, वास्तव में यह सब तीन शब्दों से मेल खाता है, क्योंकि यह प्रत्येक मैच के बाद फिर से खोज:

foo = re.search("foo", str) != None 
bar = re.search("bar", str) != None 
if foo^bar: 
    # do someting... 
0

मैं के खिलाफ Regex कोच के साथ की कोशिश की।
आप इस व्यवहार नहीं करना चाहते हैं, तो आप अभिव्यक्ति लंगर कर सकते हैं, शब्द सीमाओं पर केवल मिलान उदाहरण के लिए:

\b(foo|bar)\b 

समस्या पर अधिक संदर्भ देते हुए (डेटा कैसा दिखता है) के सही उत्तर दे सकता है।

0
\b(foo)\b|\b(bar)\b 

और केवल पहले capture group का उपयोग करें।

15

अपने regex भाषा का समर्थन करता है, तो negative lookaround का उपयोग करें:

(?<!foo|bar)(foo|bar)(?!foo|bar) 

यह "foo" से मेल खाते हैं या "बार" जाता है कि तुरंत पहले या "foo" द्वारा पीछा नहीं होगा या "बार", जो मुझे लगता है वह वही है जो आप चाहते थे।

यदि आपके द्वारा मिलान करने की कोशिश कर रहे स्ट्रिंग में अन्य टोकन हो सकते हैं तो यह आपके प्रश्न या उदाहरण से स्पष्ट नहीं है: "foocuzbar"। यदि ऐसा है, तो यह पैटर्न काम नहीं करेगा।

यहाँ अपने परीक्षण मामलों के परिणाम हैं ("सच" का अर्थ पैटर्न इनपुट में पाया गया था):

foo: true 
bar: true 
foofoo: false 
barfoo: false 
foobarfoo: false 
barbar: false 
barfoofoo: false 
+2

मुझे नकारात्मक लुकराउंड के बारे में सिखाने के लिए धन्यवाद :) – SocialCensus

+0

यह पूरी तरह से काम करता है लेकिन पर्ल में नहीं, fyi – Keng

+0

मेरे लिए यहां सबसे अच्छा जवाब है। परीक्षण पृष्ठ पर ठीक काम करता है https://regex101.com – Ralf

0

शब्द सीमाओं का उपयोग करके आप एक शब्द प्राप्त कर सकते हैं ...

[email protected] ~ 
$ echo "Where is my bar of soap?" | egrep "\bfoo\b|\bbar\b" 
Where is my bar of soap? 

[email protected] ~ 
$ echo "What the foo happened here?" | egrep "\bfoo\b|\bbar\b" 
What the foo happened here? 

[email protected] ~ 
$ echo "Boy, that sure is foobar\!" | egrep "\bfoo\b|\bbar\b" 
2

आपने दूसरे के अनुपस्थिति में "foo" और "bar" या दो की पुनरावृत्ति के अलावा अन्य सामग्री के संबंध में व्यवहार निर्दिष्ट नहीं किया है। उदाहरण के लिए, "foo डी" या "बारबार ian" मैच होना चाहिए?

मान लीजिए कि आप स्ट्रिंग्स से मिलान करना चाहते हैं जिसमें "foo" या "bar" का केवल एक उदाहरण शामिल है, लेकिन स्ट्रिंग में किसी और चीज़ के संबंध में, दोनों के एक से अधिक उदाहरण नहीं हैं, यानी " भोजन "मैचों और" बर्बर "मेल नहीं खाते हैं), तो आप एक रेगेक्स का उपयोग कर सकते हैं जो मिले मैचों की संख्या देता है और केवल एक मैच मिलने पर ही इसे सफल मानता है। जैसे, पर्ल में:

@matches = ($value =~ /(foo|bar)/g) # @matches now hold all foos or bars present 
if (scalar @matches == 1) {   # exactly one match found 
    ... 
} 

है कि एक ही लक्ष्य के कई repetitions अनुमति दी जाती है (यानी, "जंगली" से मेल खाता है), तो यह एक ही सामान्य दृष्टिकोण तो मैचों की सूची चलने से इस्तेमाल किया जा सकता मैचों को देखने के लिए कि क्या सभी एक ही पाठ की दोहराव हैं या यदि दूसरा विकल्प भी मौजूद है।

1

यदि आप एक वास्तविक अनन्य चाहते हैं या, मैं बस रेगेक्स के बजाय कोड में ऐसा करूंगा। पर्ल में:

/foo/ xor /bar/ 

लेकिन अपनी टिप्पणी:

से मेल खाता है: "foo" "बार" nonmatches: "foofoo" "barfoo" "foobarfoo" "barbar" "barfoofoo"

इंगित करता है कि आप वास्तव में अनन्य या नहीं ढूंढ रहे हैं। आप वास्तव में का मतलब है "क्या /foo|bar/ बिल्कुल एक बार मैच करता है?"

/^(foo|bar){1}$/ 

देखें:

my $matches = 0; 
while (/foo|bar/g) { 
    last if ++$matches > 1; 
} 

my $ok = ($matches == 1) 
26

यह मैं क्या उपयोग है http://www.regular-expressions.info/quickstart.html पुनरावृत्ति के तहत

+1

स्वीकृत उत्तर की तुलना में अधिक सुरुचिपूर्ण समाधान, खासकर जब आपको 2 से अधिक मामले मिलते हैं .. –

+0

आपने '{1}' क्यों जोड़ा, इसका क्या अर्थ है? – oriadam

+0

यह गलत है, इसका मतलब केवल 'foo' या' bar' का मिलान केवल एक बार किया जाना चाहिए। – Karl

6

यह 'foo' और 'बार', लेकिन 'foobar' न कि 'blafoo' का समय लगेगा और नहीं 'blabar':

/^(foo|bar)$/ 

^ = mark start of string (or line) 
$ = mark end of string (or line) 

यह 'foo' और 'बार' और 'foo बार' और 'बार-foo' लेकिन 'foobar' का समय लगेगा और नहीं 'blafoo' न कि 'blabar':

/\b(foo|bar)\b/ 

\b = mark word boundry 
0

मैं जानता हूँ कि यह एक देर से प्रवेश है, लेकिन सिर्फ जो दूसरों के लिए देख जा सकता है मदद करने के लिए:

(/b(?:(?:(?!foo)bar)|(?:(?!bar)foo))/b) 
संबंधित मुद्दे