0

我使用 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
4

2 回答 2

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是提前知道有多少列。它从一行的开头开始(^在多行模式下)并使用接下来的五个看起来像字段的东西。它没有我想要的那么有效,因为它总是在最后一列上过冲,在回溯到行尾之前消耗“真实”行分隔符和下一行的第一个字段。如果您的文档非常大,那可能是个问题。

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

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

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

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

查看在线演示

于 2012-06-08T17:39:52.763 回答
0

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

于 2012-06-08T14:25:10.423 回答