web-dev-qa-db-ja.com

カンマと二重引用符を含む文字列をCSVに書き込みます

Suitescript 2.0を呼び出すサーバー側JavaScriptを実行するCRMシステムであるNetSuiteで、30,000以上の商品のGoogleショッピングフィードを作成しようとしています。基本的に、それは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以上のアイテムに対してそれを行うことはそれほど心配していません...

誰かがここで何が起こっているのか知っていますか?見落としている本当にシンプルなものがあるように感じます...

10
B1gJ4k3

CSV仕様 に従って、すでに引用されている文字列内に二重引用符を含めるには、2つの二重引用符( "")を使用する必要があることがわかります。私が変更され:

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

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

私も削除しました

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

CSVの列は既に引用されているため。これらは不要です。

18
B1gJ4k3

この単純な関数を使用して、string[][]をcsvファイルに変換します。セルに",またはその他の空白(空白を除く)が含まれている場合は、セルを引用します。

/**
 * 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');
}
2
Michael_Scharf

私の場合、引用する必要のない文字列を引用したくありませんでした。だから私はそれを引用する前に厄介なキャラクターのトリングをテストします。

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