regex hive multiline

Hive RegexSerDe Multiline Log matching



(3)

Parece que hay una serie de problemas con su expresión regular.

Primero, quite sus corchetes dobles.

En segundo lugar, /A y /Z / /z deben coincidir con el comienzo y el final de la entrada , no solo con una línea. Cambie /A a ^ para que coincida con el inicio de la línea, pero no cambie /z a $ ya que de hecho desea hacer coincidir el final de la entrada en este caso.

En tercer lugar, ¿quiere hacer coincidir (.*?) , No (.*)? . El primer patrón es no codicioso, mientras que el segundo patrón es ambicioso pero opcional. Debería haber coincidido con toda tu entrada hasta el final, ya que permitiste que fuera seguido por el final de la entrada.

Cuarto,. no coincide con las nuevas líneas. Puede usar (/s|/S) lugar, o ([x]|[^x]) , etc., cualquier par de coincidencias complementarias.

En quinto lugar, si te estaba dando coincidencias de una sola línea con /A y /Z / /z entonces la entrada también era una sola línea cuando anclabas toda la cadena.

Sugiero tratar de hacer coincidir solo /n , si nada coincide, las nuevas líneas no están incluidas.

No puede agregar /m al final ya que la expresión regular no incluye delimitadores. Intentará hacer coincidir los caracteres literales /m lugar y por eso no obtuviste ninguna coincidencia.

Si fuera a funcionar, la expresión regular que desea sería:

"^([0-9:- ]{19},[0-9]{3}) (//[[A-Z]*//]) ([0-9a-z-]*) ([//s//S]*?)(?=//r?//n([0-9:-] ){19},[0-9]|//r?//z)"

Descompostura:

^([0-9:- ]{19},[0-9]{3})

Combina el inicio de la nueva línea y 19 caracteres que son dígitos, : , - o más una coma, tres dígitos y un espacio. Capture todo menos el espacio final (la marca de tiempo).

(//[[A-Z]*//])

Coincide con un literal [ , cualquier cantidad de letras MAYÚSCULAS, incluso ninguna, un literal ] y un espacio. Capture todo menos el espacio final (el nivel de error).

([0-9a-z-]*)

Haga coincidir cualquier número de dígitos, letras minúsculas o - y un espacio. Capture todo menos el espacio final (la identificación del mensaje).

([//s//S]*?)(?=//r?//n([0-9:-] ){19},[0-9]|//r?//Z)

Coincide con cualquier personaje en espacios en blanco o no en blanco (cualquier personaje) pero coincide con ungreedy *? . Deje de emparejar cuando un nuevo registro o el final de la entrada ( /Z ) esté inmediatamente adelante. En este caso, no desea unir el final de la línea como una vez más, solo obtendrá una línea en su salida. Capture todo menos el final (el texto del mensaje). El /r?/n es omitir la nueva línea final al final de su mensaje, como lo es /r?/Z También podría escribir /r?/n/z Nota: capital /Z incluye la nueva línea final al final de la entrada, si es que hay una. Minúscula /z coincide al final de la entrada solamente, no a la línea nueva antes del final de la entrada. He agregado /z? en caso de que tenga que lidiar con terminaciones de línea de Windows, sin embargo, no creo que esto sea necesario.

Sin embargo, sospecho que a menos que pueda alimentar todo el archivo de una vez en lugar de línea por línea, esto tampoco funcionará.

Otra prueba simple que puedes probar es:

"^([//s//S]+)^//d"

Si funciona, coincidirá con cualquier línea completa seguida de un dígito de línea en la línea siguiente (el primer dígito de su marca de tiempo).

Estoy buscando un regex que pueda alimentar a una declaración de "crear tabla externa" de Hive QL en forma de

"input.regex"="the regex goes here"

La condición es que los registros en los archivos que el RegexSerDe debe leer son de la siguiente forma:

2013-02-12 12:03:22,323 [DEBUG] 2636hd3e-432g-dfg3-dwq3-y4dsfq3ew91b Some message that can contain any special character, including linebreaks. This one does not have a linebreak. It just has spaces on the same line. 2013-02-12 12:03:24,527 [DEBUG] 265y7d3e-432g-dfg3-dwq3-y4dsfq3ew91b Some other message that can contain any special character, including linebreaks. This one does not have one either. It just has spaces on the same line. 2013-02-12 12:03:24,946 [ERROR] 261rtd3e-432g-dfg3-dwq3-y4dsfq3ew91b Some message that can contain any special character, including linebreaks. This is a special one. This has a message that is multi-lined. This is line number 4 of the same log. Line 5. 2013-02-12 12:03:24,988 [INFO] 2632323e-432g-dfg3-dwq3-y4dsfq3ew91b Another 1-line log 2013-02-12 12:03:25,121 [DEBUG] 263tgd3e-432g-dfg3-dwq3-y4dsfq3ew91b Yet another one line log.

Estoy usando el siguiente código para crear una tabla externa:

CREATE EXTERNAL TABLE applogs (logdatetime STRING, logtype STRING, requestid STRING, verbosedata STRING) ROW FORMAT SERDE ''org.apache.hadoop.hive.contrib.serde2.RegexSerDe'' WITH SERDEPROPERTIES ( "input.regex" = "(//A[[0-9:-] ]{19},[0-9]{3}) (//[[A-Z]*//]) ([0-9a-z-]*) (.*)?(?=(?://A[[0-9:-] ]{19},[0-9]|//z))", "output.format.string" = "%1$s //[%2$s//] %3$s %4$s" ) STORED AS TEXTFILE LOCATION ''hdfs:///logs-application'';

Aquí está la cosa:

Puede extraer todas las PRIMERAS LÍNEAS de cada registro. Pero no las otras líneas de registros que tienen más de una línea. Intenté todos los enlaces, reemplacé /z con /Z al final, reemplacé /A con ^ y /Z o /z con $ , nada funcionó. ¿Me falta algo en %4$s output.format.string? o ¿no estoy usando la expresión regular correctamente?

Lo que hace la expresión regular:

Primero coincide con la marca de tiempo, seguido del tipo de registro ( DEBUG o INFO o lo que sea), luego la ID (mezcla de letras minúsculas, números y guiones) seguido de NADA, hasta que se encuentre la siguiente marca de tiempo, o hasta el final de la entrada se encuentra para que coincida con la última entrada de registro. También intenté agregar /m al final, en cuyo caso, la tabla generada tiene todos los valores NULL.


No sé mucho sobre Hive, pero la siguiente expresión regular, o una variación formateada para cadenas de Java, podría funcionar:

(/d{4}-/d/d-/d/d /d/d:/d/d:/d/d,/d+) /[([a-zA-Z_-]+)/] ([/w-]+) ((?:[^/n/r]+)(?:[/n/r]{1,2}/s[^/n/r]+)*)

Esto se puede ver haciendo coincidir sus datos de muestra aquí:

http://rubular.com/r/tQp9iBp4JI

Un desglose

  • (/d{4}-/d/d-/d/d /d/d:/d/d:/d/d,/d+) La fecha y la hora (grupo de captura 1)
  • /[([a-zA-Z_-]+)/] El nivel de registro (grupo de captura 2)
  • ([/w-]+) La identificación de la solicitud (grupo de captura 3)
  • ((?:[^/n/r]+)(?:[/n/r]{1,2}/s[^/n/r]+)*) El mensaje potencialmente multilínea (grupo de captura 4 )

Los primeros tres grupos de captura son bastante simples.

El último podría ser un poco extraño, pero está funcionando en rubular. Un desglose

( Capture it as one group (?:[^/n/r]+) Match to the end of the line, dont capture (?: Match line by line, after the first, but dont capture [/n/r]{1,2} Match the new-line /s Only lines starting with a space (this prevents new log-entries from matching) [^/n/r]+ Match to the end of the line )* Match zero or more of these extra lines )

Usé [^/n/r] lugar de . porque parece que RegexSerDe deja el . hacer coincidir nuevas líneas ( enlace ):

// Excerpt from https://github.com/apache/hive/blob/trunk/contrib/src/java/org/apache/hadoop/hive/contrib/serde2/RegexSerDe.java#L101 if (inputRegex != null) { inputPattern = Pattern.compile(inputRegex, Pattern.DOTALL + (inputRegexIgnoreCase ? Pattern.CASE_INSENSITIVE : 0)); } else { inputPattern = null; }

Espero que esto ayude.


Seguir Java regex puede ayudar:

(/d{4}-/d{1,2}-/d{1,2}/s+/d{1,2}:/d{1,2}:/d{1,2},/d{1,3})/s+(/[.+?/])/s+(.+?)/s+([/s/S/s]+?)(?=/d{4}-/d{1,2}-/d{1,2}|/Z)

Descompostura:

  • 1er grupo de captura (/d{4}-/d{1,2}-/d{1,2}/s+/d{1,2}:/d{1,2}:/d{1,2},/d{1,3})
  • 2º grupo de captura (/[.+?/])
  • 3er grupo de captura (.+?)
  • 4º grupo de captura ([/s/S]+?) .

(?=/d{4}-/d{1,2}-/d{1,2}|/Z) Posicionamiento anticipado - Afirme que la expresión regular a continuación puede corresponderse.1ª Alternativa: /d{4}-/d{1,2}-/d{1,2} .2nd Alternativa: /Z afirma la posición al final de la cadena.

Referencia http://regex101.com/