从 Amazon Redshift UNLOAD 创建对 RFC-4180 友好的 CSV 文件的最佳方法是啥?
Posted
技术标签:
【中文标题】从 Amazon Redshift UNLOAD 创建对 RFC-4180 友好的 CSV 文件的最佳方法是啥?【英文标题】:What's the best way to create RFC-4180-friendly CSV files from Amazon Redshift UNLOAD?从 Amazon Redshift UNLOAD 创建对 RFC-4180 友好的 CSV 文件的最佳方法是什么? 【发布时间】:2016-01-28 18:37:38 【问题描述】:在使用 UNLOAD
时,Amazon Redshift 并没有真正的 CSV 选项(例如,类似于 PostgreSQL 的 COPY
命令中的 WITH CSV
)。
如果您使用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
如果我们同时使用ESCAPE
和ADDQUOTES
,您会得到您在初始问题示例中看到的结果。
如果我们使用ADDQUOTES
但我们不使用ESCAPE
,那么它将在数据中的双引号中中断。 Example
当然,如果我们不使用其中任何一个,我们也会使用逗号和可能的引号来换行。
是否有可用的解决方法来同时容纳数据中的引号和逗号?
【问题讨论】:
从文档来看,它似乎也不够聪明,只能在需要引号时添加引号。 在一个完美的世界里,你会添加一个RFC4180
子句,它就会开始遵守标准。
【参考方案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。
干杯!
【讨论】:
以上是关于从 Amazon Redshift UNLOAD 创建对 RFC-4180 友好的 CSV 文件的最佳方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 aws unload 命令将数据从 AWS Redshift 卸载到 s3?
Amazon Redshift - 卸载到 S3 - 动态 S3 文件名