Regex 如何替换仅出现在事物之间的分隔符?

Regex 如何替换仅出现在事物之间的分隔符?,regex,scala,apache-spark,regex-lookarounds,regexp-replace,Regex,Scala,Apache Spark,Regex Lookarounds,Regexp Replace,我有一个使用此数据的用例: 1. "apple+case" 2. "apple+case+10+cover" 3. "apple+case+10++cover" 4. "+apple" 5. "iphone8+" 目前,我这样做是为了将+替换为空格,如下所示: def normalizer(value: String): String = { if (value == null) { null } else { value.replaceAll("\\

我有一个使用此数据的用例:

1. "apple+case"
2. "apple+case+10+cover"
3. "apple+case+10++cover"
4. "+apple"
5. "iphone8+"
目前,我这样做是为了将+替换为空格,如下所示:

def normalizer(value: String): String = {
    if (value == null) {
      null
    } else {
       value.replaceAll("\\+", BLANK_SPACE)        
     }
  }

  val testUDF = udf(normalizer(_: String): String)

  df.withColumn("newCol",  testUDF($"value"))
但这将取代所有的“+”。如何替换字符串之间的“+”,同时处理诸如“apple+case+10++cover”=>“apple case 10+cover”之类的用例


您可以尝试替换两个正则表达式:

df.withColumn("newCol", regexp_replace(
    regexp_replace(testUDF("value"), "(?<=\d)\+(?!\+)", "+ "),
    "(?<!\d)\+", " ")).show
然后,外部正则表达式的替换对象是前面没有数字的所有加号,并用空格替换它们。示例,从上面继续:

apple+case+10+ cover -->  apple case 10+ cover

您可以使用
regexp\u replace
而不是udf来执行此操作,它应该更快。在大多数情况下,您可以在regexp中使用负前瞻,但对于“+apple”,您实际上希望将“+”替换为“”(而不是空格)。最简单的方法是简单地使用regexp

df.withColumn("newCol", regexp_replace($"value", "^\\+", ""))
  .withColumn("newCol", regexp_replace($"newCol", "\\+(?!\\+|$)", " "))
这将提供:

+--------------------+--------------------+
|value               |newCol              |
+--------------------+--------------------+
|apple+case          |apple case          |
|apple+case+10+cover |apple case 10 cover |
|apple+case+10++cover|apple case 10+ cover|
|+apple              |apple               |
|iphone8+            |iphone8+            |
+--------------------+--------------------+

为了使其更加模块化和可重用,您可以将其定义为一个函数:

def normalizer(c: String) = regexp_replace(regexp_replace(col(c), "^\\+", ""), "\\+(?!\\+|$)", " ")

df.withColumn("newCol", normalizer("value"))

这并不能取代“Apple + Case+ 10 +覆盖”和“Apple + Case+ 10 + +覆盖”-通过这一测试似乎只适用于单一的“+”,我认为“代码> Apple + Case+ 10 +覆盖< /代码>是坏数据。你真的有这些数据吗?是的。它是一个常见的用例。至少我希望++替换为单个“”(最坏情况解决方案)testUDF(“值”)应该已经替换字符串中的所有+,对吗?tat应该是外部的吗?@user3407267请检查更新的答案,它现在应该可以工作了。问题是我需要在多个DFs中应用这一点,这就是为什么认为UDF是更干净的方法。请让我知道,如果你有任何其他更干净,更快的方法,我可以应用于多个领域DFs@user3407267:如果您想,您只需将regexp放入您的UDF中,它仍然可以工作。但是您也可以在方法中使用
regexp\u replace
(保持速度),我在答案中添加了一些信息。
+--------------------+--------------------+
|value               |newCol              |
+--------------------+--------------------+
|apple+case          |apple case          |
|apple+case+10+cover |apple case 10 cover |
|apple+case+10++cover|apple case 10+ cover|
|+apple              |apple               |
|iphone8+            |iphone8+            |
+--------------------+--------------------+
def normalizer(c: String) = regexp_replace(regexp_replace(col(c), "^\\+", ""), "\\+(?!\\+|$)", " ")

df.withColumn("newCol", normalizer("value"))