在Scala的数据框中应用regex_replace时,如何解决“当前不支持'E'类型的文字”异常?

时间:2018-08-25 06:34:51

标签: regex postgresql scala apache-spark

我有一个通过读取RDBMS表创建的数据框,如下所示:

val dataDF = spark.read.format("jdbc").option("url", connectionUrl)
                                                .option("dbtable", s"(${query}) as year2017")
                                                .option("user", devUserName)
                                                .option("password", devPassword)
                                                .option("numPartitions",15)
                                                .load()

在将数据提取到HDFS上的Hive表中之前,我们被要求在String数据类型的数据帧的列上应用regex_replace模式。这就是我的应用方式:

val regExpr = dataDF.schema.fields.map { x =>
  if (x.dataType == StringType)
  "regexp_replace(regexp_replace(regexp_replace(regexp_replace(regexp_replace(%s, E'[\\\\n]+', ' ', 'g' ), E'[\\\\r]+', ' ', 'g' ), E'[\\\\t]+', ' ', 'g' ), E'[\\\\cA]+', ' ', 'g' ), E'[\\\\ca]+', ' ', 'g' ) as %s".format(x.name, x.name)
  else
    x.name
}
dataDF.selectExpr(regExpr:_*)

但是当我执行代码时,它以以下异常结尾:

Exception in thread "main" org.apache.spark.sql.catalyst.parser.ParseException:
Literals of type 'E' are currently not supported.(line 1, pos 88)

== SQL ==
regexp_replace(regexp_replace(regexp_replace(regexp_replace(regexp_replace(period_name, E'[\\n]+', ' ', 'g' ), E'[\\r]+', ' ', 'g' ), E'[\\t]+', ' ', 'g' ), E'[\\cA]+', ' ', 'g' ), E'[\\ca]+', ' ', 'g' ) as period_name
----------------------------------------------------------------------------------------^^^

我使用以下命令打印了模式:println(dataDF.schema)。该代码正确识别了String列,您可以在其中看到列名称:period_name

Schema: StructType(StructField(forecast_id,LongType,true), StructField(period_num,DecimalType(15,0),true), StructField(period_name,StringType,true), StructField(drm_org,StringType,true), StructField(ledger_id,LongType,true), StructField(currency_code,StringType,true)) 

要求是删除多种格式的空格。 “字符串”列中的数据可以包含带有多种格式的空格的值。

1,             b,c,   d,

e,Ωåf

存在多个空格,制表符空间,换行符之后出现的值,如果有的话删除特殊字符等, 上一行应转换为:1,b,c,d,e,f

读取的表存在于postgres数据库中。我试图理解为什么E导致异常,但是我没有头绪。谁能让我知道如何解决此异常?

1 个答案:

答案 0 :(得分:1)

出于测试目的,我创建了一个数据框,其中在 col3 列中使用提供的带有特殊字符的字符串作为

+----+----+--------------------------------------------------------------------+
|col1|col2|col3                                                                |
+----+----+--------------------------------------------------------------------+
|a   |1   |1,          -   b,c,   d,
                 |
                 |e,Ωåf|
+----+----+--------------------------------------------------------------------+

然后按照注释中的建议使用选择带字符串类型的列使用foldleft和withColumn 使用regexp_replace在withColumn 中,您可以执行以下

//getting column names which are string type
val stringColumns = df.schema.fields.filter(_.dataType == StringType).map(_.name)
//applying regex to replace all characters except digits, characters (a to z and A to Z) and commas
import org.apache.spark.sql.functions._
val finaldf = stringColumns.foldLeft(df){(tempdf, colName) => tempdf.withColumn(colName, regexp_replace(col(colName), "[ ](?=[ ])|[^,A-Za-z0-9]+", ""))}

因此finaldf将与

+----+----+-----------+
|col1|col2|col3       |
+----+----+-----------+
|a   |1   |1,b,c,d,e,f|
+----+----+-----------+ 

您可以根据需要更改 regex模式 [ ](?=[ ])|[^,A-Za-z0-9]+。目前,A-Za-z0-9个字符仅未删除

我希望答案会有所帮助