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

Bri*_* D. 6 csv amazon-redshift

Amazon Redshift在使用时并没有真正的CSV选项UNLOAD(例如,类似于WITH CSVPostgreSQL 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
Run Code Online (Sandbox Code Playgroud)
  • 如果我们使用ESCAPE但不是ADDQUOTES,Excel等人继续打破所有逗号上的列,包括"转义"的(\,).
  • 如果我们同时使用两者ESCAPE,ADDQUOTES您将获得初始问题示例中的结果.
  • 如果我们使用ADDQUOTES但我们不使用ESCAPE那么它将打破数据中的双引号.
  • 当然,如果我们不使用任何一个,那么我们也会打破逗号和可能的引号.

有没有可用的解决方法,可以容纳数据中的引号和逗号?

Tau*_*kas 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
Run Code Online (Sandbox Code Playgroud)

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

测试示例:

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

输出:

"","""""Hi\\""","\\","<tab>"
Run Code Online (Sandbox Code Playgroud)

需要 PERL 或其他高级正则表达式引擎来执行正确的后视操作。

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

但是,我没有测试aws s3 cp部分,因为我使用另一个工具将 S3 内容获取到 STDIN。

干杯!