繁体   English   中英

解析包含带引号的逗号和换行符的逗号分隔值

[英]Parsing comma-separated values containing quoted commas and newlines

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

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

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

任何人都可以帮我解析这个。

谢谢

__ 更多解释

使用 Main Sting 我需要将它们分开

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

问题是:对于 Julie、KameL、Titi 有换行符 /n 或
在 KameL 和 Titi 之间,timmy、tomy、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

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

描述

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

(?:^|,\\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'

概括

在此处输入图片说明

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

尝试这个:

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,汤姆
多多
朱莉,卡梅利蒂
上帝
蒂米,托米,托尼,蒂尼
.

有关用于解析 CSV 的体面的 Java 兼容正则表达式,请参阅此相关答案

它承认:

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

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

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


注意:虽然我在这里发布了关于我发现的“体面”正则表达式的这个答案,只是为了节省人们搜索一个,它绝不是健壮的。 我仍然同意用户“fgv”的这个回答:最好使用 CSV 解析器。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM