2013-02-26 86 views
5

मैं एक जटिल क्वेरी के आधार पर तार का एक संग्रह फिल्टर करने के लिए की जरूरत है - में यह है "कच्चे" फार्म यह इस तरह दिखता है:जावास्क्रिप्ट regex पैटर्न मैच कई तार (और, या) एक स्ट्रिंग के खिलाफ

nano* AND (regulat* OR *toxic* OR ((risk OR hazard) AND (exposure OR release))) 

तार में से एक का एक उदाहरण से मिलान करने के खिलाफ:

Workshop on the Second Regulatory Review on Nanomaterials, 30 January 2013, Brussels 

तो, मैं का उपयोग कर और या और वाइल्डकार्ड वर्णों से मेल खानी चाहिए - तो, ​​मुझे लगता है मैं जावास्क्रिप्ट में एक regex का उपयोग करना होगा।

मैं यह सब सही ढंग से पाशन, छानने और आम तौर पर काम कर रहा है, लेकिन मैं 100% यकीन है कि मेरे regex गलत है हूँ - और कुछ परिणाम को गलत तरीके से छोड़े गए किया जा रहा है - यहाँ यह है:

/(nano[a-zA-Z])?(regulat[a-zA-Z]|[a-zA-Z]toxic[a-zA-Z]|((risk|hazard)*(exposure|release)))/i 

किसी भी मदद करेगा बहुत सराहना कीजिए - मैं वास्तव में इस वाक्यविन्यास को समझने के लिए अपने दिमाग को सही ढंग से अमूर्त नहीं कर सकता!

अद्यतन:

कुछ लोगों जिस क्रम में regex का निर्माण किया है के महत्व को इंगित करते हैं, फिर भी मैं पाठ स्ट्रिंग्स कि खोज की जाएगी पर कोई नियंत्रण नहीं है, इसलिए मैं एक समाधान है कि कर सकते हैं खोजने की जरूरत है आदेश या तो परवाह किए बिना काम करते हैं।

अद्यतन:

अंततः चहचहाना एपीआई 1.0 की निंदा की वजह से, एक PHP समाधान का इस्तेमाल किया है, उदाहरण के समारोह के लिए pastebin (मैं जानता हूँ कि इसे यहाँ कोड पेस्ट करने के लिए बेहतर है, लेकिन वहाँ एक बहुत कुछ है ...) देखें:

समारोह: http://pastebin.com/MpWSGtHK उपयोग: http://pastebin.com/pP2AHEvk

सभी के लिए धन्यवाद मदद

+0

आप का प्रयास करना चाहें [एक जीवित RegExp परीक्षण उपकरण] (http://www.gethifi.com/tools/regex)। – Barney

+0

आपके उदाहरण स्ट्रिंग में, 'नैनो' 'नियामक' के बाद आता है, लेकिन आपके रेगेक्स में, यह दूसरी तरफ गोल है। क्या इस में कोई अपेक्षित पैटर्न है कि कोई हमेशा दूसरे के सामने आ जाएगा? कुछ और उदाहरण आपकी आवश्यकता को समझाने में मदद करेंगे। –

+0

@ बार्नी - अच्छी सलाह, इस तरह मुझे यह –

उत्तर

19

एक एकल regex इस के लिए सही उपकरण, IMO नहीं है:।

/^(?=.*\bnano)(?=(?:.*\bregulat|.*toxic|(?=.*(?:\brisk\b|\bhazard\b))(?=.*(?:\bexposure\b|\brelease\b))))/i.test(subject)) 

सच लौट यदि स्ट्रिंग मापदंड आप उल्लिखित को पूरा होगा, लेकिन मैं नेस्टेड लुकहेड ढूंढें काफी समझ में नहीं आता है। जावास्क्रिप्ट टिप्पणी की regexes समर्थित है, यह इस तरह दिखेगा:

^     # Anchor search to start of string 
(?=.*\bnano)  # Assert that the string contains a word that starts with nano 
(?=    # AND assert that the string contains... 
(?:    # either 
    .*\bregulat  # a word starting with regulat 
|    # OR 
    .*toxic   # any word containing toxic 
|    # OR 
    (?=    # assert that the string contains 
    .*    # any string 
    (?:   # followed by 
    \brisk\b  # the word risk 
    |    # OR 
    \bhazard\b # the word hazard 
    )    # (end of inner OR alternation) 
)    # (end of first AND condition) 
    (?=    # AND assert that the string contains 
    .*    # any string 
    (?:   # followed by 
    \bexposure\b # the word exposure 
    |    # OR 
    \brelease\b # the word release 
    )    # (end of inner OR alternation) 
)    # (end of second AND condition) 
)    # (end of outer OR alternation) 
)     # (end of lookahead assertion) 

ध्यान दें कि पूरे regex अग्रदर्शी दावे से बना है, इसलिए मैच परिणाम ही हमेशा खाली स्ट्रिंग होगा।

इसके बजाय, आप एक regexes इस्तेमाल कर सकते हैं:

if (/\bnano/i.test(str) && 
    ( 
     /\bregulat|toxic/i.test(str) || 
     ( 
      /\b(?:risk|hazard)\b/i.test(str) && 
      /\b(?:exposure|release)\b/i.test(str) 
     ) 
    ) 
) /* all tests pass */ 
+0

बहुत अच्छा - अब इसे आजमाएं .. धन्यवाद! –

+0

कृपया आप [\ b] को समझा सकते हैं - मैंने पढ़ा है कि "\ b एक बैकस्पेस वर्ण है" लेकिन मुझे यकीन नहीं है कि यह कैसे प्रासंगिक है? –

+0

@QLStudio: सामान्य स्ट्रिंग में, "\ b" 'वास्तव में एक बैकस्पेस है चरित्र। एक regex में, '/ \ b /' ('नया Regex (" \\ b ") के बराबर') एक [शब्द सीमा एंकर] है (http://www.regular-expressions.info/wordboundaries.html)। यह एंकर एक अल्फान्यूमेरिक शब्द की शुरुआत या अंत में मेल खाता है। इसलिए '/ \ brisk \ b /' केवल "जोखिम" से मेल खाता है या '" एक है जोखिम! "', लेकिन '" तेज "या' जोखिम भरा नहीं "'। –

2

रेगुलर एक्सप्रेशन क्रम में स्ट्रिंग के माध्यम से आगे बढ़ना है। पैटर्न में "regulat" से पहले आपके पास "नैनो" है, लेकिन वे परीक्षण स्ट्रिंग में बदल गए हैं। यह करने के लिए regexen उपयोग करने के बजाय, मैं सादे पुराने स्ट्रिंग पार्स साथ रहना चाहते हैं:

if (str.indexOf('nano') > -1) { 
    if (str.indexOf('regulat') > -1 || str.indexOf('toxic') > -1 
     || ((str.indexOf('risk') > - 1 || str.indexOf('hazard') > -1) 
     && (str.indexOf('exposure') > -1 || str.indexOf('release') > -1) 
    )) { 
     /* all tests pass */ 
    } 
} 

आप वास्तव में शब्द पर कब्जा करने (जैसे "नियामक" कहाँ "regulat" से है मिलता है, मैं विभाजित होगा चाहते हैं शब्द के व्यवधान द्वारा सजा और निरीक्षण अलग-अलग शब्दों

+1

@EP - कृपया मेरी टिप्पणी ऊपर देखें, जिस स्ट्रिंग के साथ मैं मिलान कर रहा हूं उसका क्रम यादृच्छिक है क्योंकि यह सामग्री है .. मैं बस कोशिश कर रहा हूं रेगेक्स के आधार पर ट्वीट्स के बड़े संग्रह पर "फ़िल्टर" करने के लिए - शायद यह गलत दृष्टिकोण है? –

+0

@QLStudio मेरा सुझाव इसके लिए अनुचित है? –

+0

@EP - हाँ, क्षमा करें - आपका समाधान ऑर्डर समस्या हल करता है .. लेकिन क्या मैं अभी भी सामान्य जेएस खोज में वाइल्डकार्ड (*) वर्णों का उपयोग कर सकता हूं? –