全部产品
Search
文档中心

云原生大数据计算服务 MaxCompute:UDF示例:使用正则表达式替换字符串

更新时间:Jul 04, 2023

本文为您介绍如何分别通过Java UDF和Python UDF实现使用正则表达式替换字符串。

命令说明

本示例将注册一个名称为UDF_REPLACE_BY_REGEXP的自定义函数,下面对命令格式和入参进行说明。

  • 命令格式:

    string UDF_REPLACE_BY_REGEXP(string <s>, string <regex>, string <replacement>) 
  • 命令功能:

    在字符串s中使用正则表达式regex匹配并替换为字符串replacement。与MaxCompute的内建函数REGEXP_REPLACE函数相比,该函数中正则表达式支持变量。

  • 参数说明:

    • s:源字符串,STRING类型,必填。

    • regex:正则表达式,STRING类型,必填。

    • replacement:替换字符串,将该字符串通过正则表达式替换源字符串,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 {
    /**
     * 上一次查询的正则表达式,缓存避免多次编译
     */
    private String lastRegex = "";
    private Pattern pattern = null;

    /**
     * @param s 源字符串
     * @param regex 正则表达式
     * @param replacement 替换字符串
     */
    public String evaluate(String s, String regex, String replacement) {
        Objects.requireNonNull(s, "原始字符串不能为null");
        Objects.requireNonNull(regex, "正则表达式不能为null");
        Objects.requireNonNull(replacement, "替换字符串不能为null");

        // 如果正则表达式已更改,再次编译正则表达式。
        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")
        # 如果正则表达式已更改,再次编译正则表达式。
        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")
        # 如果正则表达式已更改,再次编译正则表达式。
        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 #  |
+--------------+