19

我正在尝试在 NetSuite 中生成包含 30,000 多个商品的 Google 购物提要,这是一个运行服务器端 JavaScript 的 CRM 系统,它调用 Suitescript 2.0。本质上,它只是带有更多限制的 JavaScript。我的任务是将此产品提要输出为 CSV。

问题是这些项目的产品描述包含可变数量的逗号、双引号、单引号和 HTML。起初,只是逗号引起了我的问题,所以经过一番研究,我将输出的字符串用双引号括起来:

//This function isn't terribly important, but is referenced below

function sanitizeString (desc) {
    var itemDesc;
    if (desc) {
        itemDesc = desc.replace(/(\r\n|\n|\r|\s+|\t| )/gm,' ');
        itemDesc = itemDesc.replace(/,/g, '\,');
        itemDesc = itemDesc.replace(/"/g, '\"');
        itemDesc = itemDesc.replace(/'/g, '\'');
        itemDesc = itemDesc.replace(/ +(?= )/g,'');
    } else {
        itemDesc = '';
    }
    return itemDesc;
}

var row = '';

for (var i = 0; i < columns.length; i++) {
    var col = columns[i];
    row += '"' + sanitizeString(val[col]) + '"';
    if (i != columns.length - 1) {
        row += ',';
    }
}
newFeed.appendLine({value: row});

然而,这些双引号似乎与字符串中的双引号发生了奇怪的交互,导致了一些奇怪的格式,即使我的 sanitizeString() 函数应该转义它们。每当描述包含双引号时,下一行都不会得到它自己的行。它被附加到最后一列。

所以,自然地,我像这样逃避了外部引用:

row += '\"' + sanitizeString(val[col]) + '\"';

这样做会让事情变得完全混乱,很多项目不会被推送到新行,并且我会最大限度地使用我允许的列数,因为它只是继续进行。

另一个自然的解决方案是去编辑产品描述,但我并不急于为 30,000 多个项目这样做......

有人知道这里可能会发生什么吗?我觉得我忽略了一些非常简单的事情......

4

3 回答 3

31

事实证明,根据CSV 规范,要在已引用的字符串中包含双引号,您需要使用两个双引号 ("")。我变了:

itemDesc = itemDesc.replace(/"/g, '\"');

itemDesc = itemDesc.replace(/"/g, '""');

我也删了

itemDesc = itemDesc.replace(/,/g, '\,');
itemDesc = itemDesc.replace(/'/g, '\'');

由于 CSV 中的列已被引用。这些都是不必要的。

于 2017-10-09T04:22:20.733 回答
4

我使用这个简单的函数将一个转换string[][]为 csv 文件。"如果单元格包含 a 、 a,或其他空格(空格除外),它会引用单元格:

/**
 * Takes an array of arrays and returns a `,` sparated csv file.
 * @param {string[][]} table
 * @returns {string}
 */
export function toCSV(table: string[][]) {
    return table
        .map(row =>
            row
                .map(cell => {
                    // We remove blanks and check if the column contains
                    // other whitespace,`,` or `"`.
                    // In that case, we need to quote the column.
                    if (cell.replace(/ /g, '').match(/[\s,"]/)) {
                        return '"' + cell.replace(/"/g, '""') + '"';
                    }
                    return cell;
                })
                .join(',')
        )
        .join('\n');
}
于 2017-11-16T23:39:41.183 回答
2

就我而言,我不想引用不需要引用的字符串。所以我在引用之前测试字符串是否有讨厌的字符。

function escapeCSV (term) {
  if (term.match && term.match(/,|"/))  {
    return `"${term.replace('"','""')}"`
  } else {
    return term
  }
}
于 2019-09-20T20:18:45.623 回答