解析包含引号和新行的逗号分隔值

时间:2013-05-13 23:53:32

标签: java regex string parsing csv

我有一些特殊字符的字符串。 目的是检索每行的String [](,分隔) 你有特殊的角色“你可以拥有/ n和

For example Main String
Alpha,Beta,Gama,"23-5-2013,TOM",TOTO,"Julie, KameL
Titi",God," timmy, tomy,tony,
tini".

您可以看到“/”中有/ n。

可以帮我解析一下。

谢谢

__更多解释

主要刺痛我需要分开这些

Here Alpha
Beta
Gama
23-5-2013,TOM
TOTO
Julie,KameL,Titi
God
timmy, tomy,tony,tini

问题是:对于Julie,KameL,Titi在KameL和Titi之间有换行符/ n或
timmy,tomy,tony,tini的类似问题在tony和tini之间有换行符/ n或


新的此文本存档(强制逐行阅读)

Alpha,Beta Charli,Delta,Delta Echo ,Frank George,Henry
1234-5,"Ida, John
 ", 25/11/1964, 15/12/1964,"40,000,000.00",0.0975,2,"King, Lincoln 
 ",Mary / New York,123456
12543-01,"Ocean, Peter

输出我想删除这个“

Alpha
Beta Charli
Delta
Delta Echo
Frank George
Henry
1234-5
Ida
John
"
25/11/1964
15/12/1964
40,000,000.00
0.0975
2
King
Lincoln
"
Mary / New York
123456
12543-01
Ocean
Peter

4 个答案:

答案 0 :(得分:5)

解析CSV比初看起来要困难得多,这就是为什么你最好的选择就是使用经过精心设计和测试的库来为你完成这项工作。两个库是opencsvsupercsv,还有许多其他库。看看两者并使用最符合您要求和风格的那个。

答案 1 :(得分:3)

描述

考虑以下powershell示例的通用正则表达式tested on a Java parser,它不需要额外的处理来重新组装数据部分。第一个匹配组将匹配报价,然后将其带到匹配结束,这样您就可以确保捕获但不包括报价之间的整个值。我也不捕获逗号,除非它们嵌入了引号分隔的子字符串。

(?:^|,\s{0,})(["]?)\s{0,}((?:.|\n|\r)*?)\1(?=[,]\s{0,}|$)

实施例

$Matches = @()
$String = 'Alpha,Beta,Gama,"23-5-2013,TOM",TOTO,"Julie, KameL\n
Titi",God,"timmy, \n
tomy,tony,tini"'
$Regex = '(?:^|,\s{0,})(["]?)\s{0,}((?:.|\n|\r)*?)\1(?=[,]\s{0,}|$)'

Write-Host start with 
write-host $String
Write-Host
Write-Host found
([regex]"(?i)(?m)$Regex").matches($String) | foreach {
    write-host "key at $($_.Groups[1].Index) = '$($_.Groups[1].Value)'`t= value at $($_.Groups[2].Index) = '$($_.Groups[2].Value)'"
    } # next match

产量

start with
Alpha,Beta,Gama,"23-5-2013,TOM",TOTO,"Julie, KameL\n
Titi",God,"timmy, \n
tomy,tony,tini"

found
key at 0 = ''   = value at 0 = 'Alpha'
key at 6 = ''   = value at 6 = 'Beta'
key at 11 = ''  = value at 11 = 'Gama'
key at 16 = '"' = value at 17 = '23-5-2013,TOM'
key at 32 = ''  = value at 32 = 'TOTO'
key at 37 = '"' = value at 38 = 'Julie, KameL\n
Titi'
key at 60 = ''  = value at 60 = 'God'
key at 64 = '"' = value at 65 = 'timmy, \n
tomy,tony,tini'

摘要

enter image description here

  • (?:启动非捕获组
  • ^需要字符串
  • 的开头
  • |
  • ,\s{0,}逗号后跟任意数量的空格
  • )关闭非捕获组
  • (启动捕获组1
  • ["]?如果它存在则会使用引号,我喜欢这样做,因为你想要包含其他字符然后引用
  • )关闭捕获组1
  • \s{0,}消耗任何空格(如果存在),这意味着您不需要稍后修剪该值
  • (启动捕获组2
  • (?:.|\n|\r)*?捕获所有字符,包括新行,非贪婪
  • )关闭捕获组2
  • \1如果有引用它会存储在第1组中,所以如果有,则需要在此处
  • (?=开始零断言向前看
  • [,]\s{0,}必须有一个逗号,后跟可选的空格
  • |
  • $字符串结尾
  • )关闭零断言前瞻

答案 2 :(得分:1)

试试这个:

String source = "Alpha,Beta,Gama,\"23-5-2013,TOM\",TOTO,\"Julie, KameL\n"
              + "Titi\",God,\" timmy, tomy,tony,\n"
              + "tini\".";

Pattern p = Pattern.compile("(([^\"][^,]*)|\"([^\"]*)\"),?");
Matcher m = p.matcher(source);

while(m.find())
{
    if(m.group(2) != null)
        System.out.println( m.group(2).replace("\n", "") );
    else if(m.group(3) != null)
        System.out.println( m.group(3).replace("\n", "") );
}

如果匹配不带引号的字符串,则结果将在第2组中返回。 带引号的字符串在第3组中返回。因此我需要在while块中进行区分。 你可能会找到一个更漂亮的方式。

<强>输出:
阿尔法
贝塔
伽马
23-5-2013,TOM
TOTO
朱莉,KameLTiti

 timmy,tomy,tony,tini

答案 3 :(得分:0)

有关解析CSV的Java兼容正则表达式,请参见this related answer

它识别:

  • 换行符(在值之后或在引号内)
  • 引用的值包含转义的双引号,例如""this""

简而言之,您将使用以下模式:(?:,|\n|^)("(?:(?:"")*[^"]*)*"|[^",\n]*|(?:\n|$))

然后在group(1)循环中收集每个Matcher find()


注意:尽管我在这里发布了关于我发现的“体面”正则表达式的答案,但仅仅是为了节省人们寻找正则表达式的力量,但这绝不是鲁棒的。我仍然同意用户“ fgv”的this answer:更喜欢CSV分析器。

相关问题