如何在scala中处理Text Qualifier分隔文件

时间:2017-10-03 06:56:03

标签: java regex scala

我有很多带文本限定符的分隔文件(每列开头和结尾都有双引号)。定界不一致,即可以有任何分隔,如逗号(,),管道(|),〜,制表符(\ t)。

我需要用文本(单列)读取此文件,然后通过考虑文本限定符来检查分隔符的数量。如果任何记录的列数少于或多于列,则应拒绝该记录并将其加载到不同的路径。

下面是3列ID,名称和DESC的测试数据。 DESC列有额外的分隔符。

  

" ID""名称"" DESC"
" 1" ," ABC"," A,B C"
" 2" ," XYZ" ," ABC很烦恼"
" 3" ," YYZ" ,""
4," XAA" ," sf,sd
  sdfsf"

由于desc字段中的新行字符

,最后一条记录被拆分为两条记录

以下是我试图处理但无法正确处理的代码。

val SourceFileDF = spark.read.text(InputFilePath)
SourceFile = SourceFile.filter("value != ''") // Removing empty records while reading
val aCnt = coalesce(length(regexp_replace($"value","[^,]", "")), lit(0)) //to count no of delimiters
val Delimitercount = SourceFileDF.withColumn("a_cnt", aCnt)
var invalidrecords= Delimitercount
                    .filter(col("a_cnt")
                    .!==(NoOfDelimiters)).toDF()
val GoodRecordsDF = Delimitercount
                .filter(col("a_cnt")
                .equalTo(NoOfDelimiters)).drop("a_cnt")

使用上面的代码,我可以拒绝所有分隔符较少或更多的记录,但如果分隔符与文本限定符一起使用则无法忽略。

先谢谢。

1 个答案:

答案 0 :(得分:1)

您可以使用replaceAllIn的闭包来删除匹配中所需的任何字符:

var y = """4 , "XAA" , "sf,sd\nsdfsf""""
val pattern = """"[^"]*(?:""[^"]*)*"""".r
y = pattern replaceAllIn (y, m => m.group(0).replaceAll("[,\n]", ""))
print(y) // => 4 , "XAA" , "sfsdnsdfsf"

请参阅Scala demo

<强>详情

  • " - 匹配"
  • [^"]* - 除"
  • 以外的任何0 +字符
  • (?:""[^"]*)* - 匹配""的0个或更多序列,然后匹配"以外的0个字符
  • " - "

代码在y中查找上述模式的所有非重叠匹配,并在找到匹配项(m)后,从匹配值中删除,和换行符(LF) (使用m.group(0).replaceAll("[,\n]", ""),其中m.group(0)是匹配值,[,\n]匹配,或换行符。