我使用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
答案 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。