我认为您可以借助以下正则表达式来实现这一点:(?<=.{2})\w+(?=.{2}@)
-
(?<=.{2}): 正面向后看 2 个字符
-
\w+: 任意单词字符
-
(?=.{2}@):2 个字符的正向前瞻,后跟文字 @
首先使用regexp_extract 从您的字符串中提取此模式。
from pyspark.sql.functions import regexp_extract, regexp_replace
df = df.withColumn(
"pattern",
regexp_extract("email", r"(?<=.{2})\w+(?=.{2}@)", 0)
)
df.show()
#+-------------------+-------+
#| email|pattern|
#+-------------------+-------+
#| abc123@gmail.com| c1|
#|123abc123@yahoo.com| 3abc1|
#| abcd@test.com| |
#+-------------------+-------+
然后使用regexp_replace 创建相同长度的* 的替换。
df = df.withColumn(
"replacement",
regexp_replace("pattern", r"\w", "*")
)
df.show()
#+-------------------+-------+-----------+
#| email|pattern|replacement|
#+-------------------+-------+-----------+
#| abc123@gmail.com| c1| **|
#|123abc123@yahoo.com| 3abc1| *****|
#| abcd@test.com| | |
#+-------------------+-------+-----------+
接下来使用派生的pattern 和replacement 列在原始email 列上再次使用regexp_replace。
为了安全起见,concat 在替换时从原始模式向后/向前看。为此,我们必须使用expr 才能使用pass the column values as parameters。
from pyspark.sql.functions import concat, expr, lit
df = df.withColumn(
"mod_email_col",
expr("regexp_replace(email, concat('(?<=.{2})', pattern, '(?=.{2}@)'), replacement)")
)
df.show()
#+-------------------+-------+-----------+-------------------+
#| email|pattern|replacement| mod_email_col|
#+-------------------+-------+-----------+-------------------+
#| abc123@gmail.com| c1| **| ab**23@gmail.com|
#|123abc123@yahoo.com| 3abc1| *****|12*****23@yahoo.com|
#| abcd@test.com| | | abcd@test.com|
#+-------------------+-------+-----------+-------------------+
最后删除中间列:
df = df.drop("pattern", "replacement")
df.show()
#+-------------------+-------------------+
#| email| mod_email_col|
#+-------------------+-------------------+
#| abc123@gmail.com| ab**23@gmail.com|
#|123abc123@yahoo.com|12*****23@yahoo.com|
#| abcd@test.com| abcd@test.com|
#+-------------------+-------------------+
注意:我添加了一个测试用例来表明如果电子邮件地址部分为 4 个字符或更少,这将不起作用。
更新:这里有一些方法可以处理电子邮件地址部分少于 4 个字符的边缘情况。
我使用的规则:
- 电子邮件地址长度超过 5:按上述操作
- 电子邮件地址长度为 3、4 或 5:保留第一个和最后一个字符,用
* 屏蔽其他字符
- 电子邮件地址长度为 1 或 2:屏蔽
@ 之前的单个字符
代码:
patA = "regexp_replace(email, concat('(?<=.{2})', pattern, '(?=.{2}@)'), replacement)"
patB = "regexp_replace(email, concat('(?<=.{1})', pattern, '(?=.{1}@)'), replacement)"
from pyspark.sql.functions import regexp_extract, regexp_replace
from pyspark.sql.functions import concat, expr, length, lit, split, when
df.withColumn("address_part", split("email", "@").getItem(0))\
.withColumn(
"pattern",
when(
length("address_part") > 5,
regexp_extract("email", r"(?<=.{2})\w+(?=.{2}@)", 0)
).otherwise(
regexp_extract("email", r"(?<=.{1})\w+(?=.{1}@)", 0)
)
).withColumn(
"replacement", regexp_replace("pattern", r"\w", "*")
).withColumn(
"mod_email_col",
when(
length("address_part") > 5, expr(patA)
).when(
length("address_part") > 3, expr(patB)
).otherwise(regexp_replace('email', '\w(?=@)', '*'))
).drop("pattern", "replacement", "address_part").show()
#+-------------------+-------------------+
#| email| mod_email_col|
#+-------------------+-------------------+
#| abc123@gmail.com| ab**23@gmail.com|
#|123abc123@yahoo.com|12*****23@yahoo.com|
#| abcde@test.com| a***e@test.com|
#| abcd@test.com| a**d@test.com|
#| ab@test.com| a*@test.com|
#| a@test.com| *@test.com|
#+-------------------+-------------------+