从Amazon Redshift UNLOAD创建RFC-4180友好的CSV文件的最佳方法是什么?

时间:2016-01-28 18:37:38

标签: csv amazon-redshift

使用UNLOAD时,Amazon Redshift确实没有CSV选项(例如,类似于PostgreSQL的WITH CSV命令中提供的COPY

如果您使用ESCAPE选项,则Redshift会使用\转义双引号。例如,Excel不知道如何处理该斜杠。根据RFC-4180

,它应该使用双引号
  

如果使用双引号括起字段,则使用双引号   出现在一个字段内必须通过前面的方式进行转义   另一个双引号。例如:

     

"aaa","b""bb","ccc"

Sooo ...引用将打破出口,除非我们能找到一种方法让Redshift正确地逃脱它们。

鉴于以下数据:

# select * from unload_test;
                 test_field                 | test_field_number
 --------------------------------------------+-------------------
 "No," she said, "that's not how we do it." |                 5
 Hi! This is a test, yo.                    |                 5
  • 如果我们使用ESCAPE但不使用ADDQUOTES,则Excel等人会继续打破所有逗号上的列,包括"转义"其中(\,)。 Example
  • 如果我们同时使用ESCAPEADDQUOTES,您将获得初始问题示例中显示的结果。
  • 如果我们使用ADDQUOTES但我们不使用ESCAPE,那么它会在数据中的双引号中断。 Example
  • 当然,如果我们不使用任何一个,那么我们也会打破逗号和可能的引号。

是否有适用于此的可用解决方案,可以同时包含数据中的引号和逗号?

1 个答案:

答案 0 :(得分:1)

缩放解决方案是使用perl / sed处理内容并将其转换为适当的CSV。

这些标志是必需的:DELIMITER ',' ADDQUOTES ESCAPE

aws s3 cp s3://mybucket/non_csv/part_0000 - | \
# Unescapes \" into "" but only when odd number of backslashes are found backwards
perl -pe 's/((?<![\\])(\\\\)*)\\"/\1""/g' | \
# Removes \ but only when odd number of backslashes are found backwards
perl -pe 's/((?<![\\])(\\\\)*)\\/\1/g' | \
# Unescapes \\ into \
sed -e 's/\\\\/\\/g' | \
aws s3 cp - s3://mybucket/csv/part_0000

我使用各种边缘情况对真实的噪声数据进行了测试,并得出了正确的结果。删除所有反斜杠,因为除了"-> ""之外,没有其他必须转义的内容,并添加了引号。

示例测试:

$ echo '"","\"\"Hi\\\\\"","\\\\","\<tab>"' | perl -pe 's/((?<![\\])(\\\\)*)\\"/\1""/g' | perl -pe 's/((?<![\\])(\\\\)*)\\/\1/g' | sed -e 's/\\\\/\\/g'

输出:

"","""""Hi\\""","\\","<tab>"

需要PERL或其他高级正则表达式引擎才能进行正确的后视。

性能不是问题,因为我使用的是网络带宽而不是CPU。但是,可以使用并行的GNU一次处理所有输出文件。

但是,我没有测试aws s3 cp部分,因为我使用了另一种工具将S3内容导入STDIN。

干杯!