大家都知道日志的形式偏非结构化,有很多特殊的字符等等,现总结一些日志中常用或者易用到的函数便于日志数据的提取、解析。
1.get_json_object,底层日志经常会被储存为json字符串的形式,如果想获得各个维度的值,往往需要这个函数把对应的值取出来,具体用法为:
get_json_object(action,'$.evt_id') 取出1111027379533
此处假设需要解析的字段叫action,action的值如下:
{
"info_json":
{"a": {"b": "300","c": "15000"},
"d": "110000",
"e": "小花",
"f": "小芳"},
" token": "1111027379533"
}
同样如果要取出d所对应的110000这个值,可用嵌套的get_json_object方法
get_json_object(get_json_object(
'{
"info_json":
{"a": {"b": "300","c": "15000"},
"d": "110000",
"e": "小花",
"f": "小芳"},
"evt_id": "1111027379533"
}','$.info_json'),'$.d')
需要注意的是,key值不要是中文,要不然hive会报错,而且,key值要用双引号括起来,json串的格式要规范。此外hive核心编程这本书中有提到一个json_tuple这个函数的用法,目前还没有用,先占个坑,回头再补。
2.regexp_extract(),这个函数相信很多博客都有提及,主要和正则表达式一起使用,以提取自己想要的那部分数据.regexp_extract(str, regexp[, idx]) - extracts a group that matches regexp
字符串正则表达式解析函数。
– 这个函数有点类似于 substring(str from ‘regexp’) ..
参数解释:
其中:
str是被解析的字符串
regexp 是正则表达式
idx是返回结果 取表达式的哪一部分 默认值为1。
0表示把整个正则表达式对应的结果全部返回
1表示返回正则表达式中第一个() 对应的结果 以此类推
注意点:
要注意的是idx的数字不能大于表达式中()的个数。
select regexp_extract('x=a3&x=18abc&x=2&y=3&x=4','x=([0-9]+)([a-z]+)',0) from default.dual;
得到的结果为:
x=18abc
select regexp_extract('x=a3&x=18abc&x=2&y=3&x=4','x=([0-9]+)([a-z]+)',1) from default.dual;
得到的结果为:
18
select regexp_extract('x=a3&x=18abc&x=2&y=3&x=4','x=([0-9]+)([a-z]+)',2) from default.dual;
得到的结果为:
abc
我们当前的语句只有2个()表达式 所以当idx>=3的时候 就会报错
此函数用法引自:http://blog.youkuaiyun.com/lxpbs8851/article/details/39202735
3.trim(去除空格),lower(取小写),upper(取大写),split
split(str,’符号’)[id],其中符号是用于分隔的符号,如果遇到特殊字符需要转移。也可以用多个分隔符进行分列,如‘\?|,’,split(str,’\?|,’)[0],表示对str同时用问号和逗号进行分列,并取出第一个数据。其他那几个函数很简单,不赘述。
4.reflect(‘java.net.URLDecoder’, ‘decode’,str) 其中str是需要转义的字符串,比如str='http://dig.lianjia.com/t.gif?r=1487668122415&d=%7B%22pid%22%3A%22lianjiamweb%22%2C%22key%22%3A%22https%3A%2F%2Fm.lianjia.com%2Fbj%2Flanrenzhaofang%2F%3Ffrom%3Dtimeline%26isappinstalled%3D0%23p3%22%2C%22action%22%3A%7B%22token%22%3A%22c9b71efc903f1f8e59f12845c4cd8978%22%2C%22tag%22%3A%22%E5%8D%95%E8%BA%AB%2F%E5%A4%AB%E5%A6%BB%22%7D%2C%22evt%22%3A%2210217%22%2C%22ljweb_channel_key%22%3A%22m_pages_lanrenzhaofangSearch%22%2C%22cid%22%3A110000%2C%22f%22%3A%22%22%2C%22uuid%22%3A%22399e1e19-18b0-4668-a907-b2a48f079d34%22%2C%22ssid%22%3A%224fe2fdc9-5078-4137-8002-9ce6ca84309d%22%7D'
,存成这样是因为避免有一些特殊字符或者中文在传输过程中发生问题,因此将其编码成这种形式,而我们在统计数据的时候需要对其进行解码,此实例解码结果如下:
http://dig.lianjia.com/t.gif?r=1487668122415&d={"pid":"lianjiamweb","key":"https://m.lianjia.com/bj/lanrenzhaofang/?from=timeline&isappinstalled=0#p3","action":{"token":"c9b71efc903f1f8e59f12845c4cd8978","tag":"单身/夫妻"},"evt":"10217","ljweb_channel_key":"m_pages_lanrenzhaofangSearch","cid":110000,"f":"","uuid":"399e1e19-18b0-4668-a907-b2a48f079d34","ssid":"4fe2fdc9-5078-4137-8002-9ce6ca84309d"}
从中可以看出单身/夫妻被解析成功,各种字符如斜杠等也被解析成功。
5.parse_url,此函数要慎用,此函数用法可参考这篇博客,侵删,http://www.cnblogs.com/itdyb/p/6236953.html ,parse_url(url,’QUERY’)解析的是url中?之后,#号之前的信息,如上面实例所示,如果用此函数解析出的是:
r=1487668122415&d={"pid":"lianjiamweb","key":"https://m.lianjia.com/bj/lanrenzhaofang/?from=timeline&isappinstalled=0
但是实际过程中,我们想要的可能是这一部分数据(问号之后的所有数据):
r=1487668122415&d={"pid":"lianjiamweb","key":"https://m.lianjia.com/bj/lanrenzhaofang/?from=timeline&isappinstalled=0#p3","action":{"token":"c9b71efc903f1f8e59f12845c4cd8978","tag":"单身/夫妻"},"evt":"10217","ljweb_channel_key":"m_pages_lanrenzhaofangSearch","cid":110000,"f":"","uuid":"399e1e19-18b0-4668-a907-b2a48f079d34","ssid":"4fe2fdc9-5078-4137-8002-9ce6ca84309d"}
可用函数嵌套的方法:
parse_url(regexp_replace(reflect('java.net.URLDecoder', 'decode',"http://dig.lianjia.com/t.gif?r=1487668122415&d=%7B%22pid%22%3A%22lianjiamweb%22%2C%22key%22%3A%22https%3A%2F%2Fm.lianjia.com%2Fbj%2Flanrenzhaofang%2F%3Ffrom%3Dtimeline%26isappinstalled%3D0%23p3%22%2C%22action%22%3A%7B%22token%22%3A%22c9b71efc903f1f8e59f12845c4cd8978%22%2C%22tag%22%3A%22%E5%8D%95%E8%BA%AB%2F%E5%A4%AB%E5%A6%BB%22%7D%2C%22evt%22%3A%2210217%22%2C%22ljweb_channel_key%22%3A%22m_pages_lanrenzhaofangSearch%22%2C%22cid%22%3A110000%2C%22f%22%3A%22%22%2C%22uuid%22%3A%22399e1e19-18b0-4668-a907-b2a48f079d34%22%2C%22ssid%22%3A%224fe2fdc9-5078-4137-8002-9ce6ca84309d%22%7D"),'\n| |#',''),'QUERY')
解析出来的结果即为上面所需结果,需要注意的是,需要用regexp_replace这个函数把\n 、空格和# 替换为空,否则parse_url还是会按照?和#为开始和结束标志进行解析。