正则表达式检测 csv 文件中包含逗号的数字的无效行

Regex to detect invalid rows in csv file with numbers containing commas

下面是我文件中的示例行。每行有 3 个数字字段。有些数字有逗号并被引用。有些行有多余的逗号(文件是从 pdf 中提取表格数据输出的)我正在尝试检测并删除有效的 3 字段匹配左侧或右侧的多余空字段。

"3,33","4,03","12,23" - valid  
2,,"3,23"             - valid  
,,"3,13",1,6 - invalid - remove first 2 commas   
,1,,"3,987", - invalid - remove comma at beginning and end  

这就是我的 - (([0-9,]*,){3}) 但是正在努力找出如何匹配可能包含或不包含数字的引号。

基本上我不清楚如果检测到报价然后如何寻找结束报价,如果没有,则不寻找任何结束报价。 感谢您的帮助!

(我正在使用 sublimetext 3 进行搜索和替换,但如果需要,我可以在 Python 中进行。)

如果您使用 python,我建议使用 csv 库:

data = '''"3,33","4,03","12,23"
2,,"3,23"
,,"3,13",1,6
,1,,"3,987",'''.split('\n')
import csv
for row in csv.reader(data):
    print(row)

输出:

['3,33', '4,03', '12,23']
['2', '', '3,23']
['', '', '3,13', '1', '6']
['', '1', '', '3,987', '']

但是如果你想做一个正则表达式,你可以:

(([0-9]*)|("[0-9,]*"),){3}

使用垂直管道 |对于“或”,所以要么是数字序列 [0-9]*,要么是用引号括起来的数字和逗号 "[0-9,]*".

看来您的字段内容可能是:

  • 一个整数\d+
  • 带引号的十进制数 "\d+,\d+"

这可以表示为(|\d+|"\d+,\d+")。您需要其中三个,以逗号分隔:

(|\d+|"\d+,\d+"),(|\d+|"\d+,\d+"),(|\d+|"\d+,\d+")

(你可以使用 (|\d+|"\d+,\d+")(,(|\d+|"\d+,\d+")){2} 来搞乱重复,但同样的事情重复三次更容易理解)。

请注意,这只是假设最后一个字段为“空”,因为这足以符合您的定义。所以我们需要把它锚定到行首和行尾:

^(|\d+|"\d+,\d+"),(|\d+|"\d+,\d+"),(|\d+|"\d+,\d+")$

这将只匹配有效行。

根据你的解释,开头和结尾可能会有多余的逗号,但没有其他字符,所以应该是:

^,*(|\d+|"\d+,\d+"),(|\d+|"\d+,\d+"),(|\d+|"\d+,\d+"),*$

这现在匹配所有行,但没有给您真正关心的内容,即中间的“好”部分。为此,您可以使用一个组(使用括号)。不过,我们已经在使用组,对于 | 替代方案,因此我们需要添加 ?: 以使它们成为非捕获:

^,*(?:|\d+|"\d+,\d+"),(?:|\d+|"\d+,\d+"),(?:|\d+|"\d+,\d+"),*$

现在,您可以将您关心的部分包装在捕获组中,为我们提供最终的正则表达式:

^,*((?:|\d+|"\d+,\d+"),(?:|\d+|"\d+,\d+"),(?:|\d+|"\d+,\d+")),*$

在正则表达式模式下搜索和替换,使用此正则表达式进行搜索,</code> 用于替换值。</p> <p>如果多个字段为空,则可能有多种可能的解决方案。如果您的三个值中的第一个和最后一个值永远不会为空,您可以相应地调整正则表达式。如果是,这将选择 <em>one</em> 一组有效值,这可能不是您想要的。例如,如果您有:</p> <pre><code>,,1,"2,3",,

那么 ,1,"2,3 (empty, 1, 2.3) 和 1,"2,3", (1, 2.3, empty) 都是可能的解决方案。默认情况下,您将获得第二个结果,因为 * 是贪心的,即第一个 ,* 将尝试“吃掉”尽可能多的逗号而不会使匹配失败。您可以像这样添加一个问号:,*? 使匹配“懒惰”或“非贪婪”,然后它只会根据需要使用尽可能多的逗号(产生第一个结果)。