2011-11-21 22 views
6

Necesito analizar un archivo de registro que contenga mensajes de protocolo FIX.Analizando el protocolo FIX en expresiones regulares?

Cada línea contiene información de encabezado (marca de tiempo, nivel de registro, punto final), seguido de una carga FIX.

He usado regex para analizar la información del encabezado en grupos nombrados. Ej:

<?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* 

entonces llego a la propia carga útil FIX (^ A es el separador entre cada etiqueta), por ejemplo:

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

necesito para extraer etiquetas específicas de este (por ejemplo, "A" de 35 =, o "blahblah" de 11 =), e ignorar todas las otras cosas - básicamente necesito ignorar cualquier cosa antes de "35 = A", y cualquier cosa después de hasta "11 = blahblah", luego ignorar cualquier cosa después de eso, etc.

Sé que hay una biblioteca que podría analizar todas y cada una de las etiquetas (http://source.kentyde.com/fixlib/overv iew), sin embargo, esperaba un enfoque simple usando regex aquí si es posible, ya que realmente solo necesito un par de etiquetas.

¿Hay una buena forma en la expresión regular para extraer las etiquetas que necesito?

Saludos, Victor

Respuesta

0

Utilice una herramienta de expresiones regulares como expresso o RegexBuddy.
¿Por qué no se divide en ^A y luego coincide con ([^=])+=(.*) por cada uno poniéndolos en un hash? También puede filtrar con un modificador que de forma predeterminada no agregará las etiquetas en las que no está interesado y que tienen una falla para todas las etiquetas que le interesan.

1

^A es en realidad \ x {01}, Así es como se muestra en vim. En perl, hice esto mediante una división en el hexágono 1 y luego una división en "=", en la segunda división, el valor [0] de la matriz es la etiqueta y el valor [1] es el valor.

9

No es necesario dividir en "\ x01", luego regex y luego filtrar. Si quería simplemente etiquetas de 34,49 y 56 (MsgSeqNum, SenderCompID y TargetCompID) que podría regex:

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

expresiones regulares simples como esto funcionará si sabe que su emisor no han incorporado datos que podrían causar un error en cualquier expresión regular simple. Específicamente:

campos
  1. Sin datos sin procesar (en realidad combinación de datos de datos en bruto como RawDataLength, RawData (95/96) o XmlDataLen, XmlData Len y (212,213)
  2. campos no codificados para cadenas Unicode como EncodedTextLen, textoEncode (354/355)

Para hacer frente a esos casos requiere mucho análisis adicional. yo uso un programa de análisis de pitón encargo pero incluso el código fixlib ha hecho referencia anteriormente se pone estos casos equivocadas. pero si sus datos están claros de estas excepciones la expresión regular anterior debería devolver una buena definición de los campos que desee.

Edit: He dejado la expresión regular anterior tal cual, pero debe revisarse para que el elemento de coincidencia final sea (?=\x01). La explicación se puede encontrar en @ tropleee's answer here.

+2

Esta es una mejor respuesta que la aceptada. Debe tener en cuenta los campos "len", seguro. Todos se olvidan de esto! Además, los mensajes FIX pueden contener caracteres de nueva línea (es decir, en la etiqueta 58), por lo que debe usar re.DOTALL para estar seguro. – noahlz

+2

Como se explica en [esta pregunta] (http://stackoverflow.com/questions/31198950/parsing-fix-message-in-regex/31199578#31199575), esta solución tiene un error: fallará cuando se realicen dos coincidencias adyacente. – tripleee

Cuestiones relacionadas