2016-06-09 22 views
0

我正在使用NodeJS傳輸csv文件並需要處理每一行。我還沒有找到一個節點csv解析器模塊,它在雙引號內正確地支持換行符。節點正則表達式匹配換行符而不是換行符之間的換行符

因此我使用的是split模塊,需要一個正則表達式來分割上會發現引號內的換行字符

類似/(\r?\n)/發現換行符,但我怎麼能省略雙引號字符串內的換行符?

例如輸入(注意第二行中的換行):

1,2,3,"foo bar baz",4,5 
2,2,3,"foo bar 
baz",4,5 
3,2,3,"foo bar baz",4,5 
inputCsvStream.pipe(split(/regex-for-newline-not-in-quotes/)).on('data', (line) => { 
    // do something with proper csv line 
}); 

謝謝!

回答

1

相反的split,您可以使用CSV Parse封裝,其中你可以寫:

var parse = require('csv-parse'); 
//... 
inputCsvStream.pipe(parse).on('data', (line) => { 
    // do something with proper csv line 
}); 

如果你確實想堅持split這個p urpose,您可以使用該功能,您在分割結果包括在捕獲組分隔符的一部分:

inputCsvStream.pipe(split(/(.*?(?:"[^"]*"*.*?)*)\r?\n/)).on('data', (line) => { 
    // ignore the empty lines between the "delimiters" 
    if (!line.length) return; 
    // do something with proper csv line 
}); 

這將帶外括號之間的部分(在正則表達式),並將其添加到管道結果。顯然split管道分隔符之間的部分,在這種情況下,總是空的字符串。所以這些需要在分裂之後被明確地消除。

+0

感謝您的想法。我曾嘗試'csv-parse'。不幸的是,它似乎沒有在雙引號內正確處理換行符。它分裂他們的線。除非我錯過了一些設置或選項。 –

-1

你可以將一個否定前向斷言底:

(\r?\n)(?![^",]*")

Regex demo

+1

時,引用的字符串有一個嵌入式的換行符後一個逗號這將無法正常工作。 – trincot

0

至少fast-csv支持這一點:

const csv = require('fast-csv'); 

csv.fromString(`\ 
1,2,3,"foo bar baz",4,5 
2,2,3,"foo bar 
baz",4,5 
3,2,3,"foo bar baz",4,5 
`).on('data', (d) => { 
    console.log(d); 
}); 

輸出:

[ '1', '2', '3', 'foo bar baz', '4', '5' ] 
[ '2', '2', '3', 'foo bar \nbaz', '4', '5' ] 
[ '3', '2', '3', 'foo bar baz', '4', '5' ] 
+0

我嘗試過'fast-csv',但它比替代品慢了很多,它似乎並不支持字符串中的實際新行(我知道在字符串中輸入\ n可以正常工作),至少在我的測試中。 –

+0

示例中的代碼_contains_字符串中的實際換行符。如果你不相信,使用'csv.fromPath('your-file.csv')'而不是'csv.fromString()'。我從中得到了相當不錯的結果,在不到半秒的時間內解析了40K條記錄。 – robertklep

+0

有趣的是,我只是試了一遍,我仍然有同樣的問題。處理流,管通過fast-csv,它仍然把它當作一條新線。 –