Ao contrário da função integrada REGEXP_REPLACE, uma função definida pelo usuário (UDF) permite usar variáveis em expressões regulares. Este tópico demonstra como implementar a UDF UDF_REPLACE_BY_REGEXP em Java ou Python que aceita o padrão regex como argumento.
Assinatura da UDF
Sintaxe:
string UDF_REPLACE_BY_REGEXP(string <s>, string <regex>, string <replacement>)
Parâmetros:
Os três parâmetros são obrigatórios e aceitam valores STRING.
|
Parâmetro |
Descrição |
|
|
String de source |
|
|
Expressão regular para correspondência com |
|
|
String de substituição para cada correspondência |
Valor de retorno: STRING
Pré-requisitos
Antes de começar, garanta que você tem:
Um projeto MaxCompute com permissões de desenvolvimento de UDF
Um ambiente de desenvolvimento Java ou Python
Etapa 1: Escrever a UDF
Escolha Java ou Python conforme seu ambiente de desenvolvimento.
UDF Java
package com.aliyun.rewrite; // Specify a package name.
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 {
/**
* The regular expression in the most recent query, which is cached to avoid multiple compilations.
*/
private String lastRegex = "";
private Pattern pattern = null;
/**
* @param s The source string.
* @param regex The regular expression.
* @param replacement The string that replaces the source string.
*/
public String evaluate(String s, String regex, String replacement) {
Objects.requireNonNull(s, "The source string cannot be null");
Objects.requireNonNull(regex, "The regular expression cannot be null");
Objects.requireNonNull(replacement, "The string that replaces the source string cannot be null");
// If the regular expression is changed, recompile the regular expression.
if (!regex.equals(lastRegex)) {
lastRegex = regex;
pattern = Pattern.compile(regex);
}
Matcher m = pattern.matcher(s);
StringBuffer sb = new StringBuffer();
// Perform text replacement.
while (m.find()) {
m.appendReplacement(sb, replacement);
}
m.appendTail(sb);
return sb.toString();
}
}
Uma UDF Java deve estender a classe UDF. A assinatura do método evaluate — três parâmetros de entrada STRING e um valor de retorno STRING — define a assinatura da UDF nas instruções SQL. Para ver as especificações completas de UDFs Java, consulte UDFs Java.
UDF Python 3
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 the regular expression is changed, recompile the regular expression.
if regex != self.lastRegex:
self.lastRegex = regex
self.pattern = re.compile(regex)
result = self.pattern.sub(replacement, s)
return result
Projetos MaxCompute executam UDFs com Python 2 por padrão. Para usar Python 3, execute set odps.sql.python.version=cp37 no nível da sessão antes de chamar a UDF. Para ver as especificações completas de UDFs Python 3, consulte UDFs Python 3.
UDF Python 2
#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 the regular expression is changed, recompile the regular expression.
if regex != self.lastRegex:
self.lastRegex = regex
self.pattern = re.compile(regex)
result = self.pattern.sub(replacement, s)
return result
Se o código da sua UDF Python 2 contiver caracteres chineses, adicione uma declaração de codificação no início do arquivo. Tanto #coding:utf-8 quanto # -*- coding: utf-8 -*- são válidos. Para ver as especificações completas de UDFs Python 2, consulte UDFs Python 2.
Etapa 2: Carregar recursos e registrar a UDF
Após escrever e testar o código da UDF, carregue-o no MaxCompute e registre-o como UDF_REPLACE_BY_REGEXP.
Java: Consulte Empacotar um programa Java, carregar o pacote e crie uma UDF MaxCompute.
Python: Consulte Carregar um programa Python e crie uma UDF MaxCompute.
Etapa 3: Usar a UDF
Execute o SQL a seguir para substituir todas as sequências de dígitos em uma string por #:
set odps.sql.python.version=cp37; -- To use a UDF in Python 3, run this command.
SELECT UDF_REPLACE_BY_REGEXP('abc 123 def 456', '\\d+', '#');
Saída esperada:
+--------------+
| _c0 |
+--------------+
| abc # def # |
+--------------+
Próximos passos
UDFs Java — Especificações e requisitos de UDFs Java
UDFs Python 3 — Especificações de UDFs Python 3
UDFs Python 2 — Especificações de UDFs Python 2