在PySpark中提取多个正则表达式匹配

8

我目前正在处理一个正则表达式,希望可以应用到PySpark数据框的列上。

这个正则表达式仅用于捕获一个组,但可能会返回多个匹配结果。遇到的问题是,似乎PySpark原生的正则表达式函数(regexp_extract和regexp_replace)仅允许进行组操作(通过$操作符)。

是否有一种本地方式(使用PySpark函数而非基于python的re.findall的udf)来获取由我的正则表达式匹配的子字符串列表(并且我不是在谈论第一个匹配中包含的组)?

我希望做到以下这样的效果:

my_regex = '(\w+)'
# Fetch and manipulate the resulting matches, not just the capturing group
df = df.withColumn(df.col_name, regexp_replace('col_name', my_regex, '$1[0] - $2[0]'))

使用 $1 表示数组中的第一个匹配项,以此类推...

您可以尝试以下正则表达式输入,以查看我希望获取的匹配项示例。

2 AVENUE DES LAPINOUS

它应该返回4个不同的匹配项,每个匹配项内有1个组。

只有一个匹配项在regex中..也许你需要这个 - rock321987
只有一个捕获组,为什么要使用 $2?你期望的最终结果是什么? - rock321987
1
很遗憾,没有办法获取所有匹配项.. 你可以使用 func.regexp_extract('col', my_regex, idx=1) 指定匹配索引..你需要编写一个UDF来实现这个功能.. - rock321987
1
这里已经提出了一个问题:https://github.com/apache/spark/pull/21985。 - rock321987
1
好的,那很遗憾,但感谢您让这件事浮出水面。希望他们不会太久才发布它,在使用正则表达式时感觉必不可少。那就用UDF吧... - Amesys
显示剩余3条评论
2个回答

10

Spark 3.1+ 中,可以使用regexp_extract_all函数来提取所有与正则表达式 regexp 匹配且对应于正则表达式组索引的字符串。

df = spark.createDataFrame([('2 AVENUE DES LAPINOUS',)], ['col'])
df.show(truncate=False)
#+---------------------+
#|col                  |
#+---------------------+
#|2 AVENUE DES LAPINOUS|
#+---------------------+

df = df.withColumn('output', F.expr(r"regexp_extract_all(col, '(\\w+)', 1)"))

df.show(truncate=False)
#+---------------------+--------------------------+
#|col                  |output                    |
#+---------------------+--------------------------+
#|2 AVENUE DES LAPINOUS|[2, AVENUE, DES, LAPINOUS]|
#+---------------------+--------------------------+

根据[SPARK-34214](https://issues.apache.org/jira/browse/SPARK-34214)和[PR 31306](https://github.com/apache/spark/pull/31306),这在PySpark中将不可用直到3.2版发布。 - Daniel Himmelstein
我可以发誓我在3.1上测试过了。 - ZygD
3
啊!您的方法可行,因为它使用了“expr”,只是没有使用“pyspark.sql.functions.regexp_extract_all”函数。 - Daniel Himmelstein

3

很遗憾,Spark中没有获取所有匹配项的方法。您可以使用idx指定匹配索引。

func.regexp_extract('col', my_regex, idx=1)

这里有一个未合并的请求,您可以在这里找到相关内容。

简而言之:目前,您需要编写一个UDF来完成此操作。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接