2011-11-21 13 views
6

मुझे एक लॉगफाइल को पार्स करने की आवश्यकता है जिसमें FIX प्रोटोकॉल संदेश हैं।रेगेक्स में फिक्सिंग FIX प्रोटोकॉल?

प्रत्येक पंक्ति में हेडर जानकारी (टाइमस्टैंप, लॉगिंग स्तर, एंडपॉइंट) होती है, उसके बाद एक FIX पेलोड होता है।

मैंने हेडर जानकारी को नामित समूहों में पार्स करने के लिए रेगेक्स का उपयोग किया है। उदाहरण के लिए:

<?P<datetime>\d{2}/\d{2}/\d{2} \d{2}:\d{2}:\d{2}.\d{6}) (?<process_id>\d{4}/\d{1,2})\s*(?P<logging_level>\w*)\s*(?P<endpoint>\w*)\s* 

मैं तो ठीक पेलोड खुद के लिए आते हैं जैसे (^ एक प्रत्येक टैग के बीच विभाजक है):

8=FIX.4.2^A9=61^A35=A...^A11=blahblah... 

मैं इस (जैसे से 'ए' से विशिष्ट टैग को निकालने के लिए की जरूरत है 35 =, या 11 = से "blahblah"), और अन्य सभी चीजों को अनदेखा करें - मूल रूप से मुझे "35 = ए" से पहले कुछ भी अनदेखा करने की आवश्यकता है, और "11 = blahblah" के बाद कुछ भी, फिर उसके बाद कुछ भी अनदेखा करें।

मुझे वहां एक पुस्तकालय पता है जो प्रत्येक टैग को पार्स करने में सक्षम हो सकता है (http://source.kentyde.com/fixlib/overv iew), हालांकि, यदि संभव हो तो मैं रेगेक्स का उपयोग करके एक साधारण दृष्टिकोण की उम्मीद कर रहा था, क्योंकि मुझे वास्तव में केवल कुछ टैग की आवश्यकता है।

क्या मुझे आवश्यक टैग निकालने के लिए रेगेक्स में कोई अच्छा तरीका है?

चीयर्स, विक्टर

उत्तर

0

expresso या regexbuddy की तरह एक regex उपकरण का उपयोग करें।
आप ^A पर क्यों विभाजित नहीं करते हैं और फिर ([^=])+=(.*) से प्रत्येक को एक हैश में डालकर मिलान करते हैं? आप एक स्विच के साथ फ़िल्टर भी कर सकते हैं जो डिफॉल्ट रूप से उन टैग्स को नहीं जोड़ता है जिनमें आप रुचि रखते हैं और जिनके लिए आप रुचि रखते हैं उन सभी टैग्स के लिए गिरावट आई है।

1

^ए वास्तव में \ x {01} है, यह सिर्फ vim में कैसे दिखाता है। पेर्ल में, मैंने हेक्स 1 पर एक विभाजन के माध्यम से ऐसा किया था और फिर दूसरे विभाजन पर "=" पर एक विभाजन, सरणी के मान [0] टैग और मान [1] मान है।

9

"\ x01" पर विभाजित करने की आवश्यकता नहीं है फिर फिल्टर को फिर से करें। तुम सिर्फ टैग करता है चाहता है तो 34,49 और 56 (MsgSeqNum, SenderCompId और TargetCompId) आप regex सकता है: यदि आप जानते हैं आपके इस डेटा है कि में एक बग का कारण बन सकता एम्बेडेड है नहीं करता है

dict(re.findall("(?:^|\x01)(34|49|56)=(.*?)\x01", raw_msg)) 

इस तरह सरल regexes काम करेंगे कोई साधारण regex। विशेष रूप से:

  1. कोई कच्चे डाटा क्षेत्रों (वास्तव में डेटा के संयोजन लेन और RawDataLength, RawData (95/96) या XmlDataLen, XmlData जैसे कच्चे डेटा (212.213)
  2. EncodedTextLen, EncodedText तरह यूनिकोड तार के लिए कोई इनकोडिंग क्षेत्रों (354/355)

उन मामलों को संभालने के लिए अतिरिक्त पार्स का एक बहुत लेता है। मैं एक कस्टम अजगर पार्सर लेकिन का उपयोग भी fixlib कोड आप ऊपर संदर्भित इन मामलों गलत हो जाता है। लेकिन अपने डेटा इन अपवादों के स्पष्ट है अगर उपरोक्त रेगेक्स को आपके वांछित क्षेत्रों का एक अच्छा निर्देश वापस करना चाहिए।

संपादित करें: मैंने उपर्युक्त रेगेक्स को छोड़ दिया है, लेकिन इसे संशोधित किया जाना चाहिए ताकि अंतिम मिलान तत्व (?=\x01) हो। स्पष्टीकरण @ ट्रोपली के answer here में पाया जा सकता है।

+2

यह स्वीकार किए गए एक से बेहतर जवाब है। निश्चित रूप से आपको "लेन" फ़ील्ड के लिए खाते की आवश्यकता है। हर कोई हमेशा इनके बारे में भूल जाता है! इसके अलावा, FIX संदेशों में न्यूलाइन वर्ण (यानी टैग 58 में) हो सकते हैं, इसलिए आपको सुनिश्चित करने के लिए re.DOTALL का उपयोग करने की आवश्यकता है। – noahlz

+2

जैसा कि [इस सवाल] में बताया गया है (http://stackoverflow.com/questions/31198950/parsing-fix-message-in-regex/31199578#31199575), इस समाधान में एक बग है - यह दो मैचों में विफल हो जाएगा सटा हुआ। – tripleee