PySpark SQL中regexp_extract报R类型字面量不支持如何解决
问题描述
在PySpark中通过SQL语法调用regexp_extract提取字段首个数字串,代码如下:
df = spark.createDataFrame([['id_20_30', 10], ['id_40_50', 30]], ['id', 'age']) df.createOrReplaceTempView("table") sql_statement=""" select regexp_extract(id, r'(\d+)', 1) as id from table """ df = spark.sql(sql_statement)
本地PySpark 3.3.0环境运行正常,但在EMR-6.6.0集群执行时抛出如下异常:
pyspark.sql.utils.ParseException: Literals of type 'R' are currently not supported.
如果去掉正则字符串前的r前缀,虽然不会抛出异常,但返回结果不符合预期。预期输出为:
+---+ | id| +---+ | 20| | 40| +---+
要求保留PySpark SQL写法解决该问题。
故障原因
- EMR-6.6.0搭载的Spark版本不支持SQL语句中
r'...'格式的raw字符串字面量,该语法是Spark高版本新增的特性,低版本SQL解析器无法识别r前缀,因此抛出类型不支持的解析异常。 - 直接去掉
r前缀后,SQL解析器会将字符串中的反斜杠\识别为转义符,导致传入正则引擎的表达式实际为(d+)而非匹配数字的(\d+),因此匹配结果错误。
可行解决方案
以下两种方案均保留SQL写法,且兼容高低版本Spark:
方案1:转义正则中的反斜杠
在SQL的正则字符串中,将反斜杠双写做转义,让SQL解析后可以得到正确的正则表达式,无需依赖raw字符串语法:
sql_statement=""" select regexp_extract(id, '(\\d+)', 1) as id from table """
执行该语句即可得到预期的提取结果。
方案2:用无反斜杠的等价正则替换
使用[0-9]字符类替代\d匹配数字,从根源上避免反斜杠转义问题:
sql_statement=""" select regexp_extract(id, '([0-9]+)', 1) as id from table """
该写法不需要处理转义,兼容性更强,运行结果和预期完全一致。
内容的提问来源于stack exchange,提问作者solopiu
相关产品推荐
相关产品推荐

