¿Parseando el protocolo FIX en expresiones regulares?

Necesito analizar archivos de registro que contengan mensajes de protocolo FIX.

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

He usado expresiones regulares para analizar la información del encabezado en grupos con nombre. P.ej:

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

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

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

Necesito extraer tags específicas de esto (por ejemplo, “A” de 35 =, o “blahblah” de 11 =), e ignorar todas las demás cosas. Básicamente necesito ignorar cualquier cosa antes de “35 = A”, y cualquier cosa después. a “11 = blahblah”, luego ignora cualquier cosa después de eso, etc.

Sin embargo, sé que hay bibliotecas que pueden analizar todas y cada una de las tags (http://source.kentyde.com/fixlib/overview), sin embargo, esperaba un enfoque simple utilizando regex aquí, si es posible, ya que realmente Solo necesito un par de tags.

¿Hay una buena manera en la expresión regular de extraer las tags que requiero?

Saludos, Victor

Utilice una herramienta de expresiones regulares como expreso o regexbuddy.
¿Por qué no te divides en ^A y luego combinas ([^=])+=(.*) Para cada uno de ellos y los pone en un hash? También puede filtrar con un interruptor que, de manera predeterminada, no agregará las tags en las que no está interesado y que tiene una caída para todas las tags que le interesan.

No es necesario dividir en “\ x01”, regex y luego filtrar. Si solo deseaba las tags 34,49 y 56 (MsgSeqNum, SenderCompId y TargetCompId) podría regex:

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

Regexes simples como este funcionarán si sabe que su remitente no tiene datos incrustados que podrían causar un error en cualquier expresión regular. Específicamente:

  1. No hay campos de datos sin procesar (en realidad, la combinación de datos len y datos sin procesar como RawDataLength, RawData (95/96) o XmlDataLen, XmlData (212,213)
  2. No hay campos codificados para cadenas Unicode como EncodedTextLen, EncodedText (354/355)

Para manejar esos casos se necesita mucho análisis adicional. Utilizo un analizador de Python personalizado, pero incluso el código de fixlib al que hace referencia anteriormente se equivoca en estos casos. Pero si sus datos están libres de estas excepciones, la expresión regular anterior debe devolver un bonito dictado de los campos deseados.

Edición: He dejado la expresión regular anterior tal como está, pero debería revisarse para que el elemento final de coincidencia sea (?=\x01) . La explicación se puede encontrar en la respuesta de @ tropleee aquí .

^ A es en realidad \ x {01}, así es como se muestra en vim. En perl, hice esto a través de una división en el hex 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.