expresiones regulares para analizar números con formato

Estoy analizando documentos que contienen grandes cantidades de números con formato, un ejemplo es:

Frc consts -- 1.4362 1.4362 5.4100 IR Inten -- 0.0000 0.0000 0.0000 Atom AN XYZXYZXYZ 1 6 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 2 1 0.40 -0.20 0.23 -0.30 -0.18 0.36 0.06 0.42 0.26 

Estas son líneas separadas, todas con un espacio inicial significativo y puede haber o no espacios en blanco al final significativos). Constan de 72,72, 78, 78 y 78 caracteres. Puedo deducir los límites entre campos. Estos son descriptibles (utilizando el formato fortran (nx = nspaces, an = n alfanum, in = integer en n columnas, fm.n = float de m caracteres con n lugares después del punto decimal) por:

  (1x,a14,1x,f10.4,13x,f10.4,13x,f10.4) (1x,a14,1x,f10.4,13x,f10.4,13x,f10.4) (1x,a4,a4,3(2x,3a7)) (1x,2i4,3(2x,3f7.2)) (1x,2i4,3(2x,3f7.2)) 

Tengo potencialmente varios miles de formatos diferentes (que puedo generar automáticamente o generar) y los estoy describiendo mediante expresiones regulares que describen los componentes. Por lo tanto, si regf10_4 representa una expresión regular para cualquier cadena que cumpla con la restricción f10.4 puedo crear una expresión regular de la forma:

 COMMENTS (\s .{14} \s regf10_4, \s{13} regf10_4, \s{13} regf10_4, ) 

Me gustaría saber si hay expresiones regulares que satisfagan la reutilización de esta manera. Existe una amplia variedad en la forma en que las computadoras y los seres humanos crean números que son compatibles con, digamos f10.4. Creo que las siguientes son todas las entradas y / o salidas legales para fortran (no necesito sufijos de la forma f o d como en 12.4f) [el formato en SO se debe leer como sin espacios iniciales para el primero, uno para el segundo, etc.]

 -1234.5678 1234.5678 // missing number 12345678. 1. 1.0000000 1.0000 1. 0. 0. .1234 -.1234 1E2 1.E2 1.E02 -1.0E-02 ********** // number over/underflow 

Deben ser robustos contra el contenido de los campos vecinos (por ejemplo, solo examinar con precisión 10 caracteres en una posición precisa. Por lo tanto, lo siguiente es legal para (a1, f5.2, a1):

 a-1.23b // -1.23 - 1.23. // 1.23 3 1.23- // 1.23 

Estoy usando Java, así que necesito construcciones de expresiones regulares compatibles con Java 1.6 (por ejemplo, no las extensiones de Perl)

Como lo entiendo, cada línea comprende uno o más campos de ancho fijo, que pueden contener tags, espacios o datos de diferentes tipos. Si conoce el ancho y los tipos de los campos, extraer sus datos es una cuestión simple de substring() , trim() y (opcionalmente) Whatever.parseWhatever() . Regexes no puede hacer ese trabajo más fácil, de hecho, todo lo que pueden hacer es hacerlo mucho más difícil.

Escáner realmente no ayuda, tampoco. Es cierto que tiene expresiones regulares predefinidas para varios tipos de valores, y realiza las conversiones por usted, pero aún necesita saber qué tipo buscar cada vez, y necesita que los campos estén separados por un delimitador que pueda reconocer. Los datos de ancho fijo no requieren delimitadores, por definición. Es posible que pueda falsificar los delimitadores haciendo una búsqueda anticipada, ya que muchos caracteres deben quedar en la línea, pero esa es solo otra forma de hacer que el trabajo sea más difícil de lo que debe ser.

Parece que el rendimiento va a ser una gran preocupación; incluso si pudiera hacer que una solución de expresiones regulares funcione, probablemente sería demasiado lento. No porque las expresiones regulares sean intrínsecamente lentas, sino por las contorsiones por las que tendrías que pasar para que encajen en el problema. Te sugiero que te olvides de las expresiones regulares para este trabajo.

Podrías empezar con esto e ir desde allí.

Esta expresión regular coincide con todos los números que ha proporcionado.
Desafortunadamente, también coincide con el 3 en 3 1.23-

 // [-+]?(?:[0-9]+(?:\.[0-9]*)?|\.[0-9]+)(?:[eE][-+]?[0-9]+)? // // Match a single character present in the list “-+” «[-+]?» // Between zero and one times, as many times as possible, giving back as needed (greedy) «?» // Match the regular expression below «(?:[0-9]+(?:\.[0-9]*)?|\.[0-9]+)» // Match either the regular expression below (attempting the next alternative only if this one fails) «[0-9]+(?:\.[0-9]*)?» // Match a single character in the range between “0” and “9” «[0-9]+» // Between one and unlimited times, as many times as possible, giving back as needed (greedy) «+» // Match the regular expression below «(?:\.[0-9]*)?» // Between zero and one times, as many times as possible, giving back as needed (greedy) «?» // Match the character “.” literally «\.» // Match a single character in the range between “0” and “9” «[0-9]*» // Between zero and unlimited times, as many times as possible, giving back as needed (greedy) «*» // Or match regular expression number 2 below (the entire group fails if this one fails to match) «\.[0-9]+» // Match the character “.” literally «\.» // Match a single character in the range between “0” and “9” «[0-9]+» // Between one and unlimited times, as many times as possible, giving back as needed (greedy) «+» // Match the regular expression below «(?:[eE][-+]?[0-9]+)?» // Between zero and one times, as many times as possible, giving back as needed (greedy) «?» // Match a single character present in the list “eE” «[eE]» // Match a single character present in the list “-+” «[-+]?» // Between zero and one times, as many times as possible, giving back as needed (greedy) «?» // Match a single character in the range between “0” and “9” «[0-9]+» // Between one and unlimited times, as many times as possible, giving back as needed (greedy) «+» Pattern regex = Pattern.compile("[-+]?(?:[0-9]+(?:\\.[0-9]*)?|\\.[0-9]+)(?:[eE][-+]?[0-9]+)?"); Matcher matcher = regex.matcher(document); while (matcher.find()) { // matched text: matcher.group() // match start: matcher.start() // match end: matcher.end() } 

Es solo una respuesta parcial, pero recibí una alerta de Escáner en Java 1.5 que puede escanear texto e interpretar números, lo que proporciona a BNF los números que pueden escanearse e interpretar con esta utilidad de Java. En principio, imagino que el BNF podría usarse para construir una expresión regular.