Athena自定义Apache日志正则匹配异常,所有字段返回空值
问题分析与解决方案
你的问题核心在于正则表达式没有匹配整个日志行,而Athena使用的Hive RegexSerDe要求正则必须完全覆盖每一行的内容——只要行内有任何部分没被正则匹配,就会导致整行的字段全部返回空值,这也是为什么COUNT(*)能得到正确行数(Athena能读取到所有行),但所有字段都为空的原因。
具体问题点
看你的原始日志行开头:
Jan 1 23:59:59 ip-172-70-12-5 172.70.1.146 - - [01/Jan/2018:23:59:59 +0000] ...
你的正则表达式直接从172.70.1.146开始匹配,但完全忽略了前面的Jan 1 23:59:59 ip-172-70-12-5 这一段内容。在线测试工具能匹配是因为你只截取了日志的后半段,但实际完整行无法被正则匹配,导致RegexSerDe无法提取任何字段。
修正后的正则表达式
我们需要先匹配开头的无关内容(用非捕获分组,避免占用表字段的分组位置),再保留你原来的16个捕获分组对应表字段。修正后的input.regex如下:
'(?:\\S+ \\S+ \\S+ \\S+ )(\\S+) (\\S+) (\\S+) \\[([0-9]*)\\/([a-zA-Z]*)\\/([0-9]*):[\\w:]+\\s[+\\-]\\d{4}\\] \"(.+?)\" (\\S+) (\\S+) \"([^\\"]*)\" \"([^\\"]*)\" \"([^\\"]*)\" \"([^\\"]*)\" \"([^\\"]*)\" (\\S+) \"([^\\"]*)\"$'
关键修改说明:
(?:\\S+ \\S+ \\S+ \\S+ ):这是一个非捕获分组,专门匹配日志开头的4个空白分隔元素(月份、日期、时间、主机名),这部分不会被映射到表的字段,只是用来消耗掉行首的无关内容,确保正则能覆盖整行。- 后面的16个捕获分组和你原来的正则完全一致,对应表中定义的16个字段,保证字段映射关系正确。
验证建议
修改表的DDL后,你可以先运行SELECT * FROM test_access_log LIMIT 5来验证字段是否正确填充。如果还有个别字段异常,可以检查对应位置的日志内容是否和正则的匹配规则一致(比如是否存在特殊字符未被覆盖)。
内容的提问来源于stack exchange,提问作者robotrobot
相关产品推荐
相关产品推荐

