سؤال

يعمل هذا الرمز:

from pyparsing import *

zipRE = "\d{5}(?:[-\s]\d{4})?" 
fooRE = "^\!\s+.*"

zipcode = Regex( zipRE )
foo = Regex( fooRE )

query = ( zipcode | foo )



tests = [ "80517", "C6H5OH", "90001-3234", "! sfs" ]

for t in tests:
    try:
        results = query.parseString( t )
        print t,"->", results
    except ParseException, pe:
        print pe

أنا عالق في قضيتين:

1 - كيفية استخدام وظيفة مخصصة لتحليل رمز مميز. على سبيل المثال، إذا أردت استخدام بعض المنطق المخصص بدلا من Regex لتحديد ما إذا كان الرقم هو الرمز البريدي. بدلا من:

zipcode = Regex( zipRE )

ربما:

zipcode = MyFunc()

2 - كيف يمكنني تحديد سلسلة السلسلة. "80001" يوزع "zipcode" ولكن كيف يمكنني تحديد هذا باستخدام النباط؟ أنا لا أقوم بتحليل سلسلة لمحتوياتها ولكن ببساطة لتحديد نوع الاستعلام هو.

هل كانت مفيدة؟

المحلول

سؤالك الثاني سهل، لذلك سأجيب على ذلك أولا. تغيير الاستعلام لتعيين أسماء النتائج على التعبيرات المختلفة:

query = ( zipcode("zip") | foo("foo") ) 

الآن يمكنك استدعاء GetName () في النتيجة التي تم إرجاعها:

print t,"->", results, results.getName()

إعطاء:

80517 -> ['80517'] zip
Expected Re:('\\d{5}(?:[-\\s]\\d{4})?') (at char 0), (line:1, col:1)
90001-3234 -> ['90001-3234'] zip
! sfs -> ['! sfs'] foo

إذا كنت ستستخدم Fooness أو Charbness من النتيجة للاتصال بوظيفة أخرى، فيمكنك القيام بذلك بتحليل الوقت عن طريق إرفاق إجراء تحليل إلى تعبيرات Foo و Zipcode:

# enclose zipcodes in '*'s, foos in '#'s
zipcode.setParseAction(lambda t: '*' + t[0] + '*')
foo.setParseAction(lambda t: '#' + t[0] + '#')

query = ( zipcode("zip") | foo("foo") ) 

الآن يعطي:

80517 -> ['*80517*'] zip
Expected Re:('\\d{5}(?:[-\\s]\\d{4})?') (at char 0), (line:1, col:1)
90001-3234 -> ['*90001-3234*'] zip
! sfs -> ['#! sfs#'] foo

لسؤالك الأول، لا أعرف بالضبط أي نوع من الوظائف التي تقصدها. توفر Pyparing العديد من دروس التحليل أكثر من مجرد Regex (مثل Word أو الكلمة الأساسية أو الكلمة الحرفية والكراهية)، وتتألف محللك من خلال الجمع بينها ب "+" و "|"، "^"، "@" '*' العاملين. على سبيل المثال، إذا كنت ترغب في تحليل رقم الضمان الاجتماعي الأمريكي، ولكن لا تستخدم Regex، فيمكنك استخدام:

ssn = Combine(Word(nums,exact=3) + '-' + 
        Word(nums,exact=2) + '-' + Word(nums,exact=4))

Word Matches للحصول على "كلمات" متجاورة تتكون من الأحرف المحددة في منشئها، وتجمع بين الرموز المتطابقة في رمز واحد.

إذا كنت ترغب في تحليل قائمة محتملة بهذه الأرقام، وحددها "/ 'S، استخدم:

delimitedList(ssn, '/')

أو إذا كان هناك ما بين 1 و 3 أعداد من هذه الأرقام، مع عدم وجود محيل، استخدم:

ssn * (1,3)

وأي تعبير يمكن أن يكون له أسماء نتائج أو تحليل الإجراءات المرفقة بها، لزيادة إثراء النتائج المحيطة بها، أو الوظيفة أثناء التحليل. يمكنك حتى إنشاء محللين متكررين، مثل قوائم المتداخلة بين الأقواس، والتعبيرات الحسابية، وما إلى ذلك باستخدام الطبقة الأمامية.

نية عندما كتبت النباطة هي أن هذا التركيبة من المحللين من كتل البناء الأساسية سيكون النموذج الأساسي لإنشاء محلل. كان فقط في إصدار لاحق أضفت Regex ك (ما كان عليه) صمام الهروب النهائي - إذا لم يستطع الأشخاص بناء محللهم، فيمكنهم العودة إلى تنسيق Regex، الذي أثبت بالتأكيد قوتها بمرور الوقت.

أو، كما يوحي أحد الملصقات الأخرى، يمكنك فتح مصدر النباط، و Subclass واحد من الفئات الموجودة، أو اكتب بنفسك، بعد هيكلها. هنا فئة من شأنها أن تتطابق مع الأحرف المقترنة:

class PairOf(Token):
    """Token for matching words composed of a pair
       of characters in a given set.
    """
    def __init__( self, chars ):
        super(PairOf,self).__init__()
        self.pair_chars = set(chars)

    def parseImpl( self, instring, loc, doActions=True ):
        if (loc < len(instring)-1 and 
           instring[loc] in self.pair_chars and
           instring[loc+1] == instring[loc]):
            return loc+2, instring[loc:loc+2]
        else:
            raise ParseException(instring, loc, "Not at a pair of characters")

لهذا السبب:

punc = r"~!@#$%^&*_-+=|\?/"
parser = OneOrMore(Word(alphas) | PairOf(punc))
print parser.parseString("Does ** this match @@@@ %% the parser?")

يعطي

['Does', '**', 'this', 'match', '@@', '@@', '%%', 'the', 'parser']

(لاحظ إغفال الواحد "؟")

نصائح أخرى

يمكنك استخدام الرمز البريدي و FOO بشكل منفصل، حتى تعرف أي واحد تطابق السلسلة.

zipresults = zipcode.parseString( t )
fooresults = foo.parseString( t )

ليس لدي pyparsing الوحدة، ولكن Regex يجب أن تكون فئة، وليس وظيفة.

ما يمكنك القيام به هو الفئة الفرعية منه وتجاوز الأساليب كما هو مطلوب لتخصيص السلوك، ثم استخدم الفئات الفرعية الخاصة بك بدلا من ذلك.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top