Spark SQL 2.4.0中regexp_extract_all函数的替代实现方案
在Spark SQL 2.4.0中实现批量提取电话号码(替代regexp_extract_all)
因为Spark SQL 2.4.0没有内置的regexp_extract_all函数,你可以通过以下两种方式实现批量提取所有匹配的电话号码:
方法一:纯Spark SQL实现(无需代码开发)
利用regexp_replace、split和filter组合实现,核心思路是把非匹配内容统一替换成分隔符,再拆分过滤空值:
SELECT original_column, filter( split( regexp_replace( original_column, -- 注意:根据你的号码格式调整正则,示例适配提供的+1/1/8开头的号码 '((8|\\+1|1)[\\- ]?)?(\\(?\\d{3}\\)?[\\- ]?)?([\\d]{3}[\\- ]?[\\d]{2}[\\- ]?[\\d]{2})', ',$0,' -- 给每个匹配到的号码前后加逗号,统一分隔符 ), ',' ), x -> x != '' -- 过滤拆分后产生的空字符串 ) AS phone_numbers FROM your_table_name
说明
regexp_replace会把每个匹配的电话号码用逗号包裹,将原字符串中所有非号码内容(比如原有的逗号、空格)转化为连续逗号;split(',')将字符串拆分为数组,此时数组中会包含空元素;filter去掉空元素,最终得到纯电话号码的数组。
方法二:自定义UDF(更灵活可靠)
如果正则替换的方式遇到复杂边缘场景处理不佳,可以编写Scala UDF实现精准匹配:
步骤1:编写并注册UDF
import org.apache.spark.sql.SparkSession import org.apache.spark.sql.functions.udf import java.util.regex.Pattern val spark = SparkSession.builder().getOrCreate() // 定义提取电话号码的UDF val extractAllPhones = udf((input: String) => { // 匹配电话号码的正则(根据实际格式调整) val phoneRegex = Pattern.compile("((8|\\+1|1)[\\- ]?)?(\\(?\\d{3}\\)?[\\- ]?)?([\\d]{3}[\\- ]?[\\d]{2}[\\- ]?[\\d]{2})") val matcher = phoneRegex.matcher(input) val result = scala.collection.mutable.ListBuffer[String]() // 遍历所有匹配结果 while (matcher.find()) { result += matcher.group() } result.toArray }) // 注册到Spark SQL中 spark.udf.register("extract_all_phones", extractAllPhones)
步骤2:在SQL中使用
SELECT original_column, extract_all_phones(original_column) AS phone_numbers FROM your_table_name
关键提示
- 正则适配:你提供的原正则针对的是
+7/8/7开头的号码,但示例数据是+1/1开头,需要根据实际业务的号码格式调整正则中的前缀部分(把(8|\+7|7)替换为(8|\+1|1)),否则会匹配不到示例中的号码; - 性能考虑:纯SQL方式适合简单场景,UDF方式在复杂匹配逻辑下更稳定,但需要注意UDF的序列化性能。
内容的提问来源于stack exchange,提问作者Alexander Lopatin
相关产品推荐
相关产品推荐

