使用新行修复CSV文件

时间:2012-06-08 14:18:36

标签: sql-server regex csv newline

我使用SQL Server Management Studio在MS SQL数据库上运行查询,并且一些字段包含新行。我选择将结果保存为csv,显然MS SQL不够智能,不能给我一个格式正确的CSV文件。

其中一些带有新行的字段用引号括起来,但有些不是,我不知道为什么(如果它们包含多个新行,它们似乎引用字段,但如果它们只包含一个新行则,谢谢微软,这很有用)。

当我尝试在Excel中打开此CSV时,由于新行,某些行是错误的,它认为一行是两行。

我该如何解决这个问题?

我以为我可以使用正则表达式。也许是这样的:

/,[^,]*\n[^,]*,/

问题在于它匹配一行的最后一个元素和下一行的第一个元素。

以下是演示此问题的示例csv:

field a,field b,field c,field d,field e
1,2,3,4,5
test,computer,I like
pie,4,8
123,456,"7

8

9",10,11
a,b,c,d,e

2 个答案:

答案 0 :(得分:2)

简单的正则表达式替换无法正常工作,但这是基于preg_replace_callback的解决方案:

function add_quotes($matches) {
    return preg_replace('~(?<=^|,)(?>[^,"\r\n]+\r?\n[^,]*)(?=,|$)~',
                        '"$0"',
                        $matches[0]);
}

$row_regex = '~^(?:(?:(?:"[^"*]")+|[^,]*)(?:,|$)){5}$~m';

$result=preg_replace_callback($row_regex, 'add_quotes', $source);

$row_regex的秘密是提前知道有多少列。它从一行的开头(多行模式中的^)开始,并消耗接下来的五个看起来像字段的东西。它并不像我喜欢的那样高效,因为它总是在最后一列上超出,消耗了真实的&#34;行分隔符和回溯到行尾之前的下一行的第一个字段。如果您的文档非常大,那可能是个问题。

如果您事先并不知道有多少列,您可以通过匹配第一行和计算匹配来发现它。当然,假设该行不包含导致问题的任何时髦字段。如果第一行包含列标题,则您不必担心这一点,也不必担心合法的引用字段。以下是我的表现方式:

preg_match_all('~\G,?[^,\r\n]++~', $source, $cols);

$row_regex = '~^(?:(?:(?:"[^"*]")+|[^,]*)(?:,|$)){' . count($cols[0]) . '}$~m';

您的示例数据仅包含换行符(\n),但我也允许使用DOS样式\r\n。 (由于该文件是由Microsoft产品生成的,因此我不担心旧版Mac风格的CR专用分隔符。)

<强> See an online demo

答案 1 :(得分:0)

如果您需要java编程解决方案,请使用OpenCSV库打开该文件。如果是手动操作,则在文本编辑器(如Vim)中打开文件并运行replace命令。如果是批处理操作,则可以使用perl命令清除CRLF。