本文為您介紹如何分別通過Java UDF和Python UDF實現使用Regex替換字串。
命令說明
本樣本將註冊一個名稱為UDF_REPLACE_BY_REGEXP的自訂函數,下面對命令格式和入參進行說明。
命令格式:
string UDF_REPLACE_BY_REGEXP(string <s>, string <regex>, string <replacement>)
命令功能:
在字串s中使用Regexregex匹配並替換為字串replacement。與MaxCompute的內建函數REGEXP_REPLACE函數相比,該函數中Regex支援變數。
參數說明:
s:源字串,STRING類型,必填。
regex:Regex,STRING類型,必填。
replacement:替換字串,將該字串通過Regex替換源字串,STRING類型,必填。
開發和使用步驟
1. 代碼開發
Java UDF 程式碼範例
package com.aliyun.rewrite; //package名稱,可以根據您的情況定義。
import com.aliyun.odps.udf.UDF;
import com.aliyun.odps.udf.annotation.UdfProperty;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@UdfProperty(isDeterministic=true)
public class ReplaceByRegExp extends UDF {
/**
* 上一次查詢的Regex,緩衝避免多次編譯
*/
private String lastRegex = "";
private Pattern pattern = null;
/**
* @param s 源字串
* @param regex Regex
* @param replacement 替換字串
*/
public String evaluate(String s, String regex, String replacement) {
Objects.requireNonNull(s, "原始字串不能為null");
Objects.requireNonNull(regex, "Regex不能為null");
Objects.requireNonNull(replacement, "替換字串不能為null");
// 如果Regex已更改,再次編譯Regex。
if (!regex.equals(lastRegex)) {
lastRegex = regex;
pattern = Pattern.compile(regex);
}
Matcher m = pattern.matcher(s);
StringBuffer sb = new StringBuffer();
// 替換文本
while (m.find()) {
m.appendReplacement(sb, replacement);
}
m.appendTail(sb);
return sb.toString();
}
}
使用Java語言編寫UDF代碼必須繼承UDF類,本例中evaluate方法定義了三個string類型的入參和string類型的傳回值,輸入參數和傳回值的資料類型將作為SQL語句中UDF的函數簽名Signature,其他代碼規範和要求請參考:UDF開發規範與通用流程(Java)。
Python3 UDF 程式碼範例
from odps.udf import annotate
import re
@annotate("string,string,string->string")
class ReplaceByRegExp(object):
def __init__(self):
self.lastRegex = ""
self.pattern = None
def evaluate(self, s, regex, replacement):
if not s or not regex or not replacement:
raise ValueError("Arguments with None")
# 如果Regex已更改,再次編譯Regex。
if regex != self.lastRegex:
self.lastRegex = regex
self.pattern = re.compile(regex)
result = self.pattern.sub(replacement, s)
return result
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
import re
@annotate("string,string,string->string")
class ReplaceByRegExp(object):
def __init__(self):
self.lastRegex = ""
self.pattern = None
def evaluate(self, s, regex, replacement):
if not s or not regex or not replacement:
raise ValueError("Arguments with None")
# 如果Regex已更改,再次編譯Regex。
if regex != self.lastRegex:
self.lastRegex = regex
self.pattern = re.compile(regex)
result = self.pattern.sub(replacement, s)
return result
當Python 2代碼中出現中文字元時,運行程式會報錯,必須在代碼頭部增加編碼聲明。固定聲明格式為#coding:utf-8
或# -*- coding: utf-8 -*-
,二者等效。更多python2 UDF規範請參考:UDF開發規範與通用流程(Python2)。
2. 上傳資源和註冊函數
完成UDF代碼開發和調試之後,將資源上傳至MaxCompute並註冊函數,本樣本註冊函數名:UDF_REPLACE_BY_REGEXP。Java UDF上傳資源與註冊函數詳情步驟請參見:打包、上傳及註冊,Python UDF請參見:上傳及註冊。
3. 使用樣本
成功註冊UDF後,執行以下命令,將字串中的所有數字替換為"#"。
set odps.sql.python.version=cp37; -- python3 UDF需要使用該命令開啟python3
SELECT UDF_REPLACE_BY_REGEXP('abc 123 def 456', '\\d+', '#');
執行結果如下:
+--------------+
| _c0 |
+--------------+
| abc # def # |
+--------------+