本文为您介绍如何分别通过Java UDF和Python UDF实现获取不包含分隔符的键值对字符串中指定Key对应的Value值。
命令说明
本示例将注册一个名称为UDF_EXTRACT_KEY_VALUE的自定义函数,下面对命令格式和入参进行说明。
命令格式:
string UDF_EXTRACT_KEY_VALUE(string <s>, string <split1>, string <split2>, string <keyname>)
命令功能:
在字符串s中使用split1分割出键值对后,再根据split2分割键值对获得键和值,最后返回键keyname对应的值。
说明该UDF不适用于字符串本身包含分隔符的情况,如果需要处理该情况请使用获取字符串(含分隔符)Value示例。
参数说明:
s:源字符串,STRING类型,必填。
split1:通过split1分割出键值对,STRING类型,必填。
split2:对分割出来的键值对使用split2进行分割,STRING类型,必填。
keyname:待获取值所对应的键名称,STRING类型,必填。
开发和使用步骤
1. 代码开发
Java UDF 代码示例
package com.aliyun.rewrite; //package名称,可以根据您的情况定义。
import com.aliyun.odps.udf.UDF;
import java.util.HashMap;
import java.util.Map;
public class ExtractKeyValue extends UDF{
private static final int KEY_VALUE_LENGTH = 2;
/**
* 使用split1分割出键值对后,再根据split2分割键值对
* @param str 源字符串
* @param split1 分割出键值对的标识
* @param split2 分割出key value的标识
* @param keyname 目标key名称
* @return 目标value
*/
public String evaluate(String str, String split1, String split2, String keyname) {
try {
// 通过split1分割出键值对
if (str == null || "".equals(str)) {
return null;
}
Map<String, String> keyValueCache = new HashMap<>(8);
String[] extractedKeyValues = str.split(split1);
// 对分割出来的键值对使用split2进行进一步分割
for (String keyValue : extractedKeyValues) {
storeKeyValue(keyValueCache, keyValue, split2);
}
// 获取目标key的value
return keyValueCache.get(keyname);
} catch (Exception e) {
return null;
}
}
/**
* 使用split对键值对进行分割,将分割后的结果缓存到keyValueCache中
*
* @param keyValueCache 分割后的键值对缓存
* @param keyValue 待分割的键值对
* @param split 分割符
*/
private void storeKeyValue(Map<String, String> keyValueCache, String keyValue, String split) {
if (keyValue == null || "".equals(keyValue)) {
return;
}
String[] keyValueArr = keyValue.split(split);
if (keyValueArr.length == KEY_VALUE_LENGTH) {
keyValueCache.put(keyValueArr[0], keyValueArr[1]);
}
}
}
使用Java语言编写UDF代码必须继承UDF类,本例中evaluate方法定义了四个string类型的入参和string类型的返回值,输入参数和返回值的数据类型将作为SQL语句中UDF的函数签名Signature,其他代码规范和要求请参考:UDF开发规范与通用流程(Java)。
Python3 UDF 代码示例
from odps.udf import annotate
@annotate("string,string,string,string->string")
class ExtractKeyValue(object):
def evaluate(self, s, split1, split2, keyname):
if not s:
return None
# 使用 split1 分割出键值对,再使用split2分割
key_value_cache = dict(kv.split(split2) for kv in s.split(split1) if kv)
# 获取目标 key 的 value
return key_value_cache.get(keyname)
MaxCompute默认使用Python 2,可以在Session级别使用命令set odps.sql.python.version=cp37
开启Python 3。更多python3 UDF规范请参考:UDF开发规范与通用流程(Python3)。
Python2 UDF 代码示例
#coding:utf-8
from odps.udf import annotate
@annotate("string,string,string,string->string")
class ExtractKeyValue(object):
def evaluate(self, s, split1, split2, keyname):
if not s:
return None
# 使用 split1 分割出键值对,再使用split2分割
key_value_cache = dict(kv.split(split2) for kv in s.split(split1) if kv)
# 获取目标 key 的 value
return key_value_cache.get(keyname)
当Python 2代码中出现中文字符时,运行程序会报错,必须在代码头部增加编码声明。固定声明格式为#coding:utf-8
或# -*- coding: utf-8 -*-
,二者等效。更多python2 UDF规范请参考:UDF开发规范与通用流程(Python2)。
2. 上传资源和注册函数
完成UDF代码开发和调试之后,将资源上传至MaxCompute并注册函数,本示例注册函数名:UDF_EXTRACT_KEY_VALUE。Java UDF上传资源与注册函数详情步骤请参见:打包、上传及注册,Python UDF请参见:上传及注册。
3. 使用示例
成功注册UDF后,执行以下命令,从键值对字符串中获取键为name的值。
set odps.sql.python.version=cp37; -- python3 UDF需要使用该命令开启python3
SELECT UDF_EXTRACT_KEY_VALUE('name:zhangsan;age:21;',';',':','name');
执行结果如下:
+----------+
| _c0 |
+----------+
| zhangsan |
+----------+