نباري سؤال
-
19-09-2019 - |
سؤال
يعمل هذا الرمز:
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
يجب أن تكون فئة، وليس وظيفة.
ما يمكنك القيام به هو الفئة الفرعية منه وتجاوز الأساليب كما هو مطلوب لتخصيص السلوك، ثم استخدم الفئات الفرعية الخاصة بك بدلا من ذلك.