适用于Athena的Regex在Spark SQL中失效,如何修改获一致结果?
Spark SQL REGEXP_EXTRACT_ALL正则匹配失败的解决方法
问题背景
在Athena中可正常提取6位大写字母元素的正则,在Spark SQL中使用REGEXP_EXTRACT_ALL时返回空数组。输入字符串为'ASEIAW,1245555,asda2dd,TPOIBV',预期输出数组['ASEIAW','TPOIBV']。
Athena执行结果正确:
SELECT REGEXP_EXTRACT_ALL('ASEIAW,1245555,asda2dd,TPOIBV' , '(\b[A-Z]{6}\b)+'), 'ASEIAW,1245555,asda2dd,TPOIBV' as INPUT;
返回结果:
_col0 |INPUT | -------------------+-----------------------------+ ['ASEIAW','TPOIBV']|ASEIAW,1245555,asda2dd,TPOIBV|
Spark SQL原语句返回空数组:
spark.sql("""SELECT REGEXP_EXTRACT_ALL('ASEIAW,1245555,asda2dd,TPOIBV' , '(\b[A-Z]{6}\b)+') as regex_out, 'ASEIAW,1245555,asda2dd,TPOIBV' as INPUT""").show()
返回结果:
+---------+--------------------+ |regex_out| INPUT| +---------+--------------------+ | []|ASEIAW,1245555,as...| +---------+--------------------+
原因分析
- 正则引擎差异:Athena基于Presto,使用RE2正则引擎,SQL字符串中的
\b直接被解析为正则的单词边界;而Spark SQL依赖Java正则引擎,字符串字面量中的\是转义字符,直接写\b会被解析为退格符,而非正则的单词边界,导致匹配失效。 - 冗余语法:原正则中的
(\b[A-Z]{6}\b)+包含多余的分组和+,REGEXP_EXTRACT_ALL本身会提取所有匹配项,无需额外重复分组。
解决方案
方案一:双重转义单词边界
将正则中的\b改为\\b,让Spark SQL正确识别为正则单词边界,同时简化冗余语法:
spark.sql("""SELECT REGEXP_EXTRACT_ALL('ASEIAW,1245555,asda2dd,TPOIBV' , '\\b[A-Z]{6}\\b') as regex_out, 'ASEIAW,1245555,asda2dd,TPOIBV' as INPUT""").show()
方案二:精准匹配逗号分隔边界
针对逗号分隔的场景,使用正向零宽断言匹配字符串首尾或逗号,避免单词边界的歧义:
spark.sql("""SELECT REGEXP_EXTRACT_ALL('ASEIAW,1245555,asda2dd,TPOIBV' , '(?<=^|,)[A-Z]{6}(?=,|$)') as regex_out, 'ASEIAW,1245555,asda2dd,TPOIBV' as INPUT""").show()
执行结果
两种方案均可得到预期输出:
+----------------+--------------------+ |regex_out |INPUT | +----------------+--------------------+ |[ASEIAW, TPOIBV]|ASEIAW,1245555,as...| +----------------+--------------------+
内容的提问来源于stack exchange,提问作者Gladiator
相关产品推荐
相关产品推荐

