Javascript 将包含逗号和双引号的字符串写入CSV

Javascript 将包含逗号和双引号的字符串写入CSV,javascript,csv,comma,double-quotes,suitescript2.0,Javascript,Csv,Comma,Double Quotes,Suitescript2.0,我正试图在NetSuite中生成一个包含30000多种商品的Google购物提要,NetSuite是一个运行服务器端JavaScript的CRM系统,它称之为SuiteScript2.0。本质上,它只是JavaScript,还有一些限制。我的任务是将此产品提要作为CSV输出 问题是这些项目的产品描述包含大量的逗号、双引号、单引号和HTML变量。起初,这只是逗号给我带来的问题,所以经过一点研究,我将输出的字符串用双引号括起来: //This function isn't terribly impo

我正试图在NetSuite中生成一个包含30000多种商品的Google购物提要,NetSuite是一个运行服务器端JavaScript的CRM系统,它称之为SuiteScript2.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});
这样做会使事情变得完全混乱,很多项目不会被推到新行,我会最大限度地增加允许的列数,因为它一直在进行

另一个自然的解决方案是编辑产品描述,但我并不急于对30000多个项目进行编辑


有人知道这里发生了什么吗?我觉得我忽略了一件非常简单的事情…

事实证明,要在已经被引用的字符串中包含双引号,需要使用两个双引号(“”)。我改变了:

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

我还删除了

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

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

我使用这个简单的函数将
字符串[][]
转换为csv文件。如果单元格包含
”、
或其他空格(空格除外),则会引用单元格:


在我的例子中,我不想引用不需要引用的字符串,所以我在引用之前测试字符串是否有讨厌的字符

function escapeCSV (term) {
  if (term.match && term.match(/,|"/))  {
    return `"${term.replace('"','""')}"`
  } else {
    return term
  }
}

如果您的转义函数应该向输出中添加反斜杠,则需要转义函数中字符串文本中的反斜杠,即,
\\,“
而不是
\,”
,或者对于包含单引号的函数,
'\\'
“\\”“
。不,不应该添加反斜杠。这只是为了逃脱他们的最后一串。添加转义反斜杠会使事情再次陷入混乱,并且不会添加新行,而是将其附加到包含引号的行的末尾……对您来说,“为最终字符串转义”意味着什么?这不意味着最后一个字符串将添加反斜杠吗?例如,如果特定字段的输入为
Hello,goodbye
,则输出应为
Hello\,goodbye
,否?对于CSV,如果您要删除换行符并将每个字段置于双引号中,我认为只需要转义双引号-尽管出于某种原因,您似乎将整行置于双引号中,这对于CSV来说是不正常的。请您的问题显示一个示例两行输入和相应的所需输出。我想我的意思是,它逃避了它们,这样它就不会导致最终输出中的确切问题。我对问题进行了编辑,以便更清楚地了解我对“row”变量所做的操作。(如果看不到循环,名称就有点不好)。我看了,看起来双引号中的双引号需要作为两个双引号来完成。所以,“你好”,“再见”,是一个字符串。但是用两个双引号替换双引号是可行的,但是我的输出中现在有两个双引号…好的,没关系。我想出来了。原来我运行了两次sanitizeString()函数。同样,根据CSV规范,带引号的列中的双引号需要表示为两个双引号(“”)。我运行了两次该函数,生成了4个双引号,转换为2.Edge大小写。如果字符串不是以引号开头,它可以包含被删除的引号,例如
Yes”“I am
。如果以引号开头,则必须以引号结尾。即使未引用术语,也必须转义引号。有趣。小心:
replace
只会替换第一次出现的。将正则表达式与
g
修饰符(
/“/g
)或新的
replaceAll
函数一起使用。
itemDesc = itemDesc.replace(/,/g, '\,');
itemDesc = itemDesc.replace(/'/g, '\'');
/**
 * 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');
}
function escapeCSV (term) {
  if (term.match && term.match(/,|"/))  {
    return `"${term.replace('"','""')}"`
  } else {
    return term
  }
}