har*_*ilg 9 regex hive multiline
我正在寻找一个正则表达式,可以提供给Hive QL的"创建外部表"声明的形式
"input.regex"="the regex goes here"
Run Code Online (Sandbox Code Playgroud)
条件是RegexSerDe必须读取的文件中的日志具有以下形式:
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.
Run Code Online (Sandbox Code Playgroud)
我使用以下创建外部表代码:
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';
Run Code Online (Sandbox Code Playgroud)
这是事情:
它能够拉出每个日志的所有第一个线路.但不是具有多行的其他日志行.我尝试了所有环节,取而代之\z以\Z在年底,替换\A与^和\Z或\z有$,毫无效果.我在output.format.string中遗漏了什么%4$s?或者我没有正确使用正则表达式?
正则表达式的作用:
它首先匹配时间戳,然后是日志类型(DEBUG或INFO其他),然后是ID(小写字母,数字和连字符的混合),然后是ANYTHING,直到找到下一个时间戳,或者直到找到输入的结尾为止匹配最后一个日志条目.我也尝试/m在最后添加,在这种情况下,生成的表具有所有NULL值.
您的正则表达式似乎存在很多问题。
首先,删除双方括号。
其次,\A和\Z/是匹配输入\z的开头和结尾,而不仅仅是一行。更改为以匹配行首,但不要更改为,因为在这种情况下您实际上想要匹配输入结束。\A^\z$
第三,你想匹配(.*?),不匹配(.*)?。第一个模式是非贪婪的,而第二个模式是贪婪的但可选的。它应该将您的整个输入与末尾相匹配,因为您允许它后面跟着输入结束。
第四,.不匹配换行符。您可以使用(\s|\S)或([x]|[^x])等任意一对互补匹配来代替。
\A第五,如果它为您提供与和\Z/ 的单行匹配,\z那么当您锚定整个字符串时,输入也是单行。
我建议尝试仅匹配\n,如果没有匹配,则不包括换行符。
您无法添加/m到末尾,因为正则表达式不包含分隔符。它会尝试匹配文字字符/m,这就是为什么你没有匹配到的原因。
如果它能工作,你想要的正则表达式将是:
"^([0-9:- ]{19},[0-9]{3}) (\\[[A-Z]*\\]) ([0-9a-z-]*) ([\\s\\S]*?)(?=\\r?\\n([0-9:-] ){19},[0-9]|\\r?\\z)"
Run Code Online (Sandbox Code Playgroud)
分解:
^([0-9:- ]{19},[0-9]{3})
Run Code Online (Sandbox Code Playgroud)
匹配换行符的开头以及 19 个字符,即数字、:或-加一个逗号、三个数字和一个空格。捕获除最后一个空格(时间戳)之外的所有内容。
(\\[[A-Z]*\\])
Run Code Online (Sandbox Code Playgroud)
匹配文字[、任意数量的大写字母(甚至没有)、文字]和空格。捕获除最后一个空间(错误级别)之外的所有空间。
([0-9a-z-]*)
Run Code Online (Sandbox Code Playgroud)
匹配任意数量的数字、小写字母或-和空格。捕获除最后一个空格(消息 ID)之外的所有内容。
([\\s\\S]*?)(?=\\r?\\n([0-9:-] ){19},[0-9]|\\r?\\Z)
Run Code Online (Sandbox Code Playgroud)
匹配任何空白或非空白字符(任何字符),但匹配 ungreedy *?。当新记录或输入结束( \Z) 紧邻时停止匹配。在这种情况下,您不想再次匹配行尾,因为您在输出中只会得到一行。捕获除最终内容(消息文本)之外的所有内容。是\r?\n跳过消息末尾的最后一个换行符,就像\r?\Z. 您还可以写\r?\n\z注释:大写\Z包括输入末尾的最后换行符(如果有的话)。小写字母\z仅在输入末尾匹配,而不在输入末尾之前匹配换行符。我添加了\z?以防万一您必须处理 Windows 行结尾,但是,我认为这不是必要的。
但是,我怀疑除非您可以立即输入整个文件而不是逐行输入,否则这也不起作用。
您可以尝试的另一个简单测试是:
"^([\\s\\S]+)^\\d"
Run Code Online (Sandbox Code Playgroud)
如果它有效,它将匹配任何整行,后跟下一行的行数字(时间戳的第一个数字)。