使用 Javascript 以逗号分隔字符串,但忽略双引号中的逗号

我正在寻找 [a, b, c, "d, e, f", g, h]转换成一个包含6个元素的数组: a,b,c,“ d,e,f”,g,h。以下是我目前掌握的情况:

str = str.split(/,+|"[^"]+"/g);

但是现在它把双引号里的所有东西都分开了,这是不正确的。

编辑: 好吧,对不起,我把这个问题写得很糟糕。我得到的是一个字符串,而不是一个数组。

var str = 'a, b, c, "d, e, f", g, h';

我想使用类似于“ split”函数的东西将 那个转换成一个数组。

98264 次浏览

假设您的字符串看起来真的像 '[a, b, c, "d, e, f", g, h]',我相信这将是‘ eval()可以接受的用例:

myString = 'var myArr ' + myString;
eval(myString);


console.log(myArr); // will now be an array of elements: a, b, c, "d, e, f", g, h

编辑 : 正如 Rocket 所指出的,strict模式取消了 eval向本地作用域注入变量的能力,这意味着您需要这样做:

var myArr = eval(myString);

我知道这有点长,但我的看法是:

var sample="[a, b, c, \"d, e, f\", g, h]";


var inQuotes = false, items = [], currentItem = '';


for(var i = 0; i < sample.length; i++) {
if (sample[i] == '"') {
inQuotes = !inQuotes;


if (!inQuotes) {
if (currentItem.length) items.push(currentItem);
currentItem = '';
}


continue;
}


if ((/^[\"\[\]\,\s]$/gi).test(sample[i]) && !inQuotes) {
if (currentItem.length) items.push(currentItem);
currentItem = '';
continue;
}


currentItem += sample[i];
}


if (currentItem.length) items.push(currentItem);


console.log(items);

作为附注,它既可以在开头和结尾使用大括号,也可以不使用大括号。

我会这么做。

var str = 'a, b, c, "d, e, f", g, h';
var arr = str.match(/(".*?"|[^",\s]+)(?=\s*,|\s*$)/g);

enter image description here /* 匹配:

    (
".*?"       double quotes + anything but double quotes + double quotes
|           OR
[^",\s]+    1 or more characters excl. double quotes, comma or spaces of any kind
)
(?=             FOLLOWED BY
\s*,        0 or more empty spaces and a comma
|           OR
\s*$        0 or more empty spaces and nothing else (end of string)
)
    

*/
arr = arr || [];
// this will prevent JS from throwing an error in
// the below loop when there are no matches
for (var i = 0; i < arr.length; i++) console.log('arr['+i+'] =',arr[i]);

这对我很有用。(我使用了分号,这样警告消息就会显示在将数组转换为字符串时添加的逗号与实际捕获的值之间的区别。)

REGEX

/("[^"]*")|[^;]+/

enter image description here

var str = 'a; b; c; "d; e; f"; g; h; "i"';
var array = str.match(/("[^"]*")|[^;]+/g);
alert(array);

我也遇到过类似的问题,但我没发现有什么好处。网络解决方案所以去 DIY。注意: 这也用于回复

分隔逗号分隔的字符串,忽略引号中的逗号,但允许使用一个双引号的字符串

但似乎更适用于这里(但在那里有用)

在我的应用程序中,我解析了一个 csv,所以我的分割凭证是“ ,”。我认为这个方法只适用于只有一个字符分割参数的情况。

因此,我编写了一个忽略双引号中逗号的函数。它通过将输入字符串转换为字符数组并逐个解析 char 来完成

public static string[] Splitter_IgnoreQuotes(string stringToSplit)
{
char[] CharsOfData = stringToSplit.ToCharArray();
//enter your expected array size here or alloc.
string[] dataArray = new string[37];
int arrayIndex = 0;
bool DoubleQuotesJustSeen = false;
foreach (char theChar in CharsOfData)
{
//did we just see double quotes, and no command? dont split then. you could make ',' a variable for your split parameters I'm working with a csv.
if ((theChar != ',' || DoubleQuotesJustSeen) && theChar != '"')
{
dataArray[arrayIndex] = dataArray[arrayIndex] + theChar;
}
else if (theChar == '"')
{
if (DoubleQuotesJustSeen)
{
DoubleQuotesJustSeen = false;
}
else
{
DoubleQuotesJustSeen = true;
}
}
else if (theChar == ',' && !DoubleQuotesJustSeen)
{
arrayIndex++;
}
}
return dataArray;
}

对于我的应用程序来说,这个函数也会忽略任何输入中的(“”) ,因为这些输入是不需要的,并且存在于我的输入中。

下面是一个 JavaScript 函数:

function splitCSVButIgnoreCommasInDoublequotes(str) {
//split the str first
//then merge the elments between two double quotes
var delimiter = ',';
var quotes = '"';
var elements = str.split(delimiter);
var newElements = [];
for (var i = 0; i < elements.length; ++i) {
if (elements[i].indexOf(quotes) >= 0) {//the left double quotes is found
var indexOfRightQuotes = -1;
var tmp = elements[i];
//find the right double quotes
for (var j = i + 1; j < elements.length; ++j) {
if (elements[j].indexOf(quotes) >= 0) {
indexOfRightQuotes = j;
break;
}
}
//found the right double quotes
//merge all the elements between double quotes
if (-1 != indexOfRightQuotes) {
for (var j = i + 1; j <= indexOfRightQuotes; ++j) {
tmp = tmp + delimiter + elements[j];
}
newElements.push(tmp);
i = indexOfRightQuotes;
}
else { //right double quotes is not found
newElements.push(elements[i]);
}
}
else {//no left double quotes is found
newElements.push(elements[i]);
}
}


return newElements;
}

一堆东西就够了。在这里,我模糊地使用标记布尔值作为堆栈(只是为了达到我的目的)。

var str = "a,b,c,blah\"d,=,f\"blah,\"g,h,";
var getAttributes = function(str){
var result = [];
var strBuf = '';
var start = 0 ;
var marker = false;
for (var i = 0; i< str.length; i++){


if (str[i] === '"'){
marker = !marker;
}
if (str[i] === ',' && !marker){
result.push(str.substr(start, i - start));
start = i+1;
}
}
if (start <= str.length){
result.push(str.substr(start, i - start));
}
return result;
};


console.log(getAttributes(str));

下面是一个非正则表达式,它假设双引号将成对出现:

function splitCsv(str) {
return str.split(',').reduce((accum,curr)=>{
if(accum.isConcatting) {
accum.soFar[accum.soFar.length-1] += ','+curr
} else {
accum.soFar.push(curr)
}
if(curr.split('"').length % 2 == 0) {
accum.isConcatting= !accum.isConcatting
}
return accum;
},{soFar:[],isConcatting:false}).soFar
}


console.log(splitCsv('asdf,"a,d",fdsa'),' should be ',['asdf','"a,d"','fdsa'])
console.log(splitCsv(',asdf,,fds,'),' should be ',['','asdf','','fds',''])
console.log(splitCsv('asdf,"a,,,d",fdsa'),' should be ',['asdf','"a,,,d"','fdsa'])

Jsfiddle 设置图像 < a href = “ https://i.stack.imgur.com/mgVnb.png”rel = “ nofollow norefrer”> 代码输出图像

如果输入字符串的格式为 stringTo 比较,则该代码可以正常工作。 在 https://jsfiddle.net/上运行代码以查看 fiddlejs 设置的输出。 请参考截图。 您可以对下面的代码使用拆分函数,并根据需要调整代码。 如果不想在分割后使用逗号,请从代码中删除使用 in * * 的粗体或单词。附加 = 附加 * * + “ ,”* * + actialString [ t + 1]。

var stringTocompare='"Manufacturer","12345","6001","00",,"Calfe,eto,lin","Calfe,edin","4","20","10","07/01/2018","01/01/2006",,,,,,,,"03/31/2004"';


console.log(stringTocompare);


var actualString=stringTocompare.split(',');
console.log("Before");
for(var i=0;i<actualString.length;i++){
console.log(actualString[i]);
}
//var actualString=stringTocompare.split(/,(?=(?:(?:[^"]*"){2})*[^"]*$)/);
for(var i=0;i<actualString.length;i++){
var flag=0;
var x=actualString[i];
if(x!==null)
{
if(x[0]=='"' && x[x.length-1]!=='"'){
var p=0;
var t=i;
var b=i;
for(var k=i;k<actualString.length;k++){
var y=actualString[k];
if(y[y.length-1]!=='"'){
p++;
}
if(y[y.length-1]=='"'){


flag=1;
}
if(flag==1)
break;
}
var attach=actualString[t];
for(var s=p;s>0;s--){


attach=attach+","+actualString[t+1];
t++;
}
actualString[i]=attach;
actualString.splice(b+1,p);
}
}




}
console.log("After");
for(var i=0;i<actualString.length;i++){
console.log(actualString[i]);
}








[1]: https://i.stack.imgur.com/3FcxM.png

正则表达式: /,(?=(?:(?:[^"]*"){2})*[^"]*$)/

enter image description here

const input_line = '"2C95699FFC68","201 S BOULEVARDRICHMOND, VA 23220","8299600062754882","2018-09-23"'


let my_split = input_line.split(/,(?=(?:(?:[^"]*"){2})*[^"]*$)/)[4]


Output:
my_split[0]: "2C95699FFC68",
my_split[1]: "201 S BOULEVARDRICHMOND, VA 23220",
my_split[2]: "8299600062754882",
my_split[3]: "2018-09-23"

参考以下链接以获得解释: Regexr.com/44u6o

这将一次获取一个 csv 文件一行,并返回一个数组,其中包含完整的语音标记内逗号。如果没有语音标记检测到它只是。如果按照正常的方式分割(“ ,”) s... ... 可能会用一些东西替换第二个循环,但它按原样执行任务

function parseCSVLine(str){
if(str.indexOf("\"")>-1){
var aInputSplit = str.split(",");
var aOutput = [];
var iMatch = 0;
//var adding = 0;
for(var i=0;i<aInputSplit.length;i++){
if(aInputSplit[i].indexOf("\"")>-1){
var sWithCommas = aInputSplit[i];
for(var z=i;z<aInputSplit.length;z++){
if(z !== i && aInputSplit[z].indexOf("\"") === -1){
sWithCommas+= ","+aInputSplit[z];
}else if(z !== i && aInputSplit[z].indexOf("\"") > -1){
sWithCommas+= ","+aInputSplit[z];
sWithCommas.replace(new RegExp("\"", 'g'), "");
aOutput.push(sWithCommas);
i=z;
z=aInputSplit.length+1;
iMatch++;
}
if(z === aInputSplit.length-1){
if(iMatch === 0){
aOutput.push(aInputSplit[z]);
}
iMatch = 0;
}
}
}else{
aOutput.push(aInputSplit[i]);
}
}
return aOutput
}else{
return str.split(",")
}
}

下面是正则表达式 我们在用,它从逗号分隔的参数列表中提取有效参数,支持双引号参数。它适用于轮廓边缘情况。例如。

  • 在比赛中不包括引号
  • 在火柴中使用空格
  • 在空地上工作

(?<=")[^"]+?(?="(?:\s*?,|\s*?$))|(?<=(?:^|,)\s*?)(?:[^,"\s][^,"]*[^,"\s])|(?:[^,"\s])(?![^"]*?"(?:\s*?,|\s*?$))(?=\s*?(?:,|$))

证明: https://regex101.com/r/UL8kyy/3/tests(注意: 目前只能在 Chrome 中使用,因为正则表达式使用了仅在 ECMA2018中支持的后退功能)

根据 我们的指导方针,它避免了非捕获组和贪婪匹配。

我确信它可以被简化,我对建议/额外的测试用例持开放态度。

对于任何感兴趣的人,第一部分匹配双引号、逗号分隔的参数:

(?<=")[^"]+?(?="(?:\s*?,|\s*?$))

第二部分与逗号分隔的参数相匹配:

(?<=(?:^|,)\s*?)(?:[^,"\s][^,"]*[^,"\s])|(?:[^,"\s])(?![^"]*?"(?:\s*?,|\s*?$))(?=\s*?(?:,|$))

我几乎喜欢这个被接受的答案,但是它没有正确地解析空格,并且/或者它没有修剪双引号,所以下面是我的函数:

    /**
* Splits the given string into components, and returns the components array.
* Each component must be separated by a comma.
* If the component contains one or more comma(s), it must be wrapped with double quotes.
* The double quote must not be used inside components (replace it with a special string like __double__quotes__ for instance, then transform it again into double quotes later...).
*
* https://stackoverflow.com/questions/11456850/split-a-string-by-commas-but-ignore-commas-within-double-quotes-using-javascript
*/
function splitComponentsByComma(str){
var ret = [];
var arr = str.match(/(".*?"|[^",]+)(?=\s*,|\s*$)/g);
for (let i in arr) {
let element = arr[i];
if ('"' === element[0]) {
element = element.substr(1, element.length - 2);
} else {
element = arr[i].trim();
}
ret.push(element);
}
return ret;
}
console.log(splitComponentsByComma('Hello World, b, c, "d, e, f", c')); // [ 'Hello World', 'b', 'c', 'd, e, f', 'c' ]

基于 TYPESCRIPT 解析任何 CSV 或 CSV-String 代码

public parseCSV(content:string):any[string]{
return content.split("\n").map(ar=>ar.split(/,(?=(?:(?:[^"]*"){2})*[^"]*$)/).map(refi=>refi.replace(/[\x00-\x08\x0E-\x1F\x7F-\uFFFF]/g, "").trim()));
}


var str='"abc",jkl,1000,qwerty6000';


parseCSV(str);

产出:

[
"abc","jkl","1000","qwerty6000"
]

我用一个简单的解析器解决了这个问题。

它只是一个字符串一个字符地遍历字符串,当它找到 split _ char (例如逗号)时会分割出一个段,但是它也有一个开/关标志,通过找到封装器 _ char (例如 quote)来切换。它不要求封装器位于字段/段的开始(a,b”,“ c,d 将生成3个段,第二个段是“ b”,“ c”) ,但是它应该适用于具有转义封装器字符的结构良好的 CSV。

function split_except_within(text, split_char, encapsulator_char, escape_char) {
var start = 0
var encapsulated = false
var fields = []
for (var c = 0; c < text.length; c++) {
var char = text[c]
if (char === split_char && ! encapsulated) {
fields.push(text.substring(start, c))
start = c+1
}
if (char === encapsulator_char && (c === 0 || text[c-1] !== escape_char) )
encapsulated = ! encapsulated
}
fields.push(text.substring(start))
return fields
}

Https://jsfiddle.net/7hty8lvr/1/

const csvSplit = (line) => {
let splitLine = [];


var quotesplit = line.split('"');
var lastindex = quotesplit.length - 1;
// split evens removing outside quotes, push odds
quotesplit.forEach((val, index) => {
if (index % 2 === 0) {
var firstchar = (index == 0) ? 0 : 1;
var trimmed = (index == lastindex)
? val.substring(firstchar)
: val.slice(firstchar, -1);
trimmed.split(",").forEach(v => splitLine.push(v));
} else {
splitLine.push(val);
}
});
return splitLine;
}

只要引号始终出现在包含需要排除的逗号的值的外部(例如 csv 文件) ,就可以使用这种方法。

如果你有像’1,2,4“2,6”,8’这样的东西 没用的。

使用 npm 库 csv-string 解析字符串,而不是拆分: https://www.npmjs.com/package/csv-string

这将处理空项