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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/46637955/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 06:49:33  来源:igfitidea点击:

Write a string containing commas and double quotes to CSV

javascriptcsvcommadouble-quotessuitescript2.0

提问by B1gJ4k3

I'm trying to produce a Google Shopping feed of 30,000+ items in NetSuite, a CRM system that runs server-side JavaScript that it calls Suitescript 2.0. Essentially, it's just JavaScript with a few more restrictions. I've been tasked with outputting this product feed as a CSV.

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

The problem is that the product descriptions of these items contain variables amounts of commas, double quotes, single quotes and HTML. At first, it was just the commas causing me problems, so after a bit of research, I wrapped the strings I was outputting in double quotes:

问题是这些项目的产品描述包含变量数量的逗号、双引号、单引号和 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});

However, it seems that these double quotes are interacting strangely with double quotes within the string causing some weird formatting, even though my sanitizeString() function should be escaping them. Any time that a description contains a double quote, the next row doesn't get it's own line. It gets appended to the last column.

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

So, naturally, I escaped the external quotes like this:

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

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

Doing that makes things go completely haywire, a lot of items don't get pushed to new lines and I max out the number of columns I'm allowed because it just keeps on going.

这样做会让事情变得完全混乱,很多项目不会被推到新的行,我最大限度地增加了我允许的列数,因为它一直在继续。

The other natural solution would be to go edit the product descriptions, but I'm not terribly anxious to do that for 30,000+ items...

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

Does anybody know what might be going on here? I feel like there's something really simple I'm overlooking...

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

回答by B1gJ4k3

It turns out that, according to the CSV specs, to include double quotes within a string that is already quoted, you need to use two double quotes (""). I changed:

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

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

to

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

I also removed

我也删了

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

Since the column in the CSV is being quoted already. These are unnecessary.

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

回答by Michael_Scharf

I use this simple function to convert an string[][]to a csv file. It quotes the cell, if it contains a ", a ,or other whitespace (except blanks):

我使用这个简单的函数将 an 转换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');
}

回答by Ray Foss

In my case, I didn't want to quote strings that did not need quoting. So I test the tring for nasty characters before quoting it.

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

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