Regex 什么';使用scala拆分这行的合适正则表达式是什么?

Regex 什么';使用scala拆分这行的合适正则表达式是什么?,regex,scala,csv,Regex,Scala,Csv,我正在尝试拆分来自CSV文件的这一行,以从这一行(示例)中获得不同的匹配组(文件有大约750k行): 1919年,“世界末日”(via@annabosch)玛格丽特·撒切尔(86岁);艾尔·恩埃尔·帕克:,P,协议 正如你所看到的,这行有四个主要部分,id,自由文本,情绪,选项。另外,内容部分有很多字符(La dama de hierro…),我不知道如何构建一个正确的正则表达式来获得如下内容:(id,txt,sent,opt) 到目前为止,我所尝试的: val fullRegex = """(

我正在尝试拆分来自CSV文件的这一行,以从这一行(示例)中获得不同的匹配组(文件有大约750k行):

1919年,“世界末日”(via@annabosch)玛格丽特·撒切尔(86岁);艾尔·恩埃尔·帕克:,P,协议

正如你所看到的,这行有四个主要部分,id,自由文本,情绪,选项。另外,内容部分有很多字符(La dama de hierro…),我不知道如何构建一个正确的正则表达式来获得如下内容:(id,txt,sent,opt)

到目前为止,我所尝试的:

val fullRegex = """(\d+),(.+?),(N|P|NEU|NONE)(,\W+|;\W+)re?""".r

对于某些行有效,但对于其他行无效。

正如布鲁诺·格里德(Bruno Grieder)在对问题的评论中指出的那样,这可以更有力地处理

如果这不是一个格式良好的CSV文件(也就是说,包含引号的字段、转义字段值中的引号等),另一种方法是认识到第一个字段确实为您提供了ID,最后两个字段确实为您提供了情感和选项。其他内容都是自由文本,因此行的结构相当简单

当然,如果文件确实是格式良好的CSV,请使用为此目的构建的库

假设这不是格式良好的CSV,首先用逗号分割,将第一个和最后两个字段放入各自的变量中,并使用逗号连接其余字段以恢复文本

我不太懂Scala,所以代码相当原始。欢迎:

val line = """919191911919,"La dama de hierro descubrió la ternura".(via@annabosch) Margaret Thatcher (86 años); ayer en el parque: http://host.com/gm2EEXqn ,P,AGREEMENT"""

val id :: rest = line.split(",").toList
val text = rest.slice(0, rest.size - 2).mkString(",")
val sentiment = rest(rest.size - 2);
val option = rest.last;

for (x <- List(id, text, sentiment, option))
  println(x)    
这是您将获得的输出:

1 this is some text with one, two, three, and four commas (,) 7 8 1. 这是一些带有一、二、三和四个逗号(,)的文本 7.
8如果确定文本用双引号括起来,可以先替换双引号内的所有逗号,然后在逗号处拆分,然后将逗号放回原处。此解决方案的缺点是,您需要使用保证不在文件中的Unicode字符

object CSVFixer {

  def main(args: Array[String]) {
    split(line) foreach println
  }

  val line = """919191911919,"La dama de hierro descubrió la ternura".(via@annabosch) Margaret Thatcher (86 años); ayer en el parque: http://host.com/gm2EEXqn ,P,AGREEMENT"""

  private val AltSep = '\u0080' // Unicode char that we reasonably expect to not have in the input
  val fieldSeparator = ","

  private[this] def unSep(s: String) = {
    val SepChr = fieldSeparator.charAt(0)
    var inQS = false
    for (c <- s) yield {
      c match {
        case '"' =>
          inQS = !inQS; c
        case SepChr if inQS =>
          AltSep
        case _ => c
      }
    }
  }

  def split(line: String) =
    unSep(line).split(fieldSeparator, -1) // do not discard trailing empty strings
      .map(_.replace(AltSep, fieldSeparator.charAt(0)))
      .map(_.replaceAll("\"", ""))

}
对象CSVFixer{
def main(参数:数组[字符串]){
分割(行)foreach println
}
val line=“”“919年”,第二天(via@annabosch)玛格丽特·撒切尔(86岁);艾尔·恩帕尔克:http://host.com/gm2EEXqn ,P,协议“”
private val AltSep='\u0080'//Unicode字符,我们有理由认为输入中不包含该字符
val fieldSeparator=“,”
private[this]def unsp(s:String)={
val SepChr=fieldSeparator.charAt(0)
var inQS=false
对于(c)
inQS=!inQS;c
如果inQS=>
阿尔塞普
案例uz=>c
}
}
}
def拆分(行:字符串)=
unsp(line).split(fieldSeparator,-1)//不要丢弃尾随的空字符串
.map(u.replace(AltSep,fieldSeparator.charAt(0)))
.map(\u0.replaceAll(“\”,“))
}

正则表达式功能强大,但有时很难正确处理并涵盖所有可能的输入格式。在这种情况下,可能不需要它

val in = """919191911919,"La dama de hierro descubrió la ternura".(via@annabosch) Margaret Thatcher (86 años); ayer en el parque: http://host.com/gm2EEXqn ,P,AGREEMENT"""
val inSplit = in.split(",")

val id   = inSplit.head                          // String = 919191911919
val txt  = inSplit.tail.init.init.mkString(",")  // free form text
val sent = inSplit.init.last                     // String = P
val opt  = inSplit.last                          // String = AGREEMENT

最简单的方法是
.splitBy(“,”)
,但是如果你有嵌套的逗号,它将不起作用。我建议你使用这样的方式:事实上@nmat,内容是自由文本,我不能期望它不包含逗号或任何其他字符。我将检查你提供的链接。任何与此regexp字符串不匹配的示例?假设字段数是固定的,我会检查。e、 您可以保证字段1、3、4中没有逗号,只需向前扫描到第一个逗号即可得到第一个字段,然后从末尾向后扫描到前两个逗号即可得到最后两个字段。第二个字段就是between@JorgeCespedes :)不是所有的问题都能用Regex或jQueryYes解决。这是我的建议。Regex并不是一根魔杖,它最适合所有的事情和工作anything@nmat是的,会的,看例子。@BrunoGrieder我在帖子下面看到了你最初的评论,我最初没有看到。
object CSVFixer {

  def main(args: Array[String]) {
    split(line) foreach println
  }

  val line = """919191911919,"La dama de hierro descubrió la ternura".(via@annabosch) Margaret Thatcher (86 años); ayer en el parque: http://host.com/gm2EEXqn ,P,AGREEMENT"""

  private val AltSep = '\u0080' // Unicode char that we reasonably expect to not have in the input
  val fieldSeparator = ","

  private[this] def unSep(s: String) = {
    val SepChr = fieldSeparator.charAt(0)
    var inQS = false
    for (c <- s) yield {
      c match {
        case '"' =>
          inQS = !inQS; c
        case SepChr if inQS =>
          AltSep
        case _ => c
      }
    }
  }

  def split(line: String) =
    unSep(line).split(fieldSeparator, -1) // do not discard trailing empty strings
      .map(_.replace(AltSep, fieldSeparator.charAt(0)))
      .map(_.replaceAll("\"", ""))

}
val in = """919191911919,"La dama de hierro descubrió la ternura".(via@annabosch) Margaret Thatcher (86 años); ayer en el parque: http://host.com/gm2EEXqn ,P,AGREEMENT"""
val inSplit = in.split(",")

val id   = inSplit.head                          // String = 919191911919
val txt  = inSplit.tail.init.init.mkString(",")  // free form text
val sent = inSplit.init.last                     // String = P
val opt  = inSplit.last                          // String = AGREEMENT