Je cherche [a, b, c, "d, e, f", g, h]
à transformer en un tableau de 6 éléments: a, b, c, "d, e, f", g, h. Je suis un peu un noob avec RegEx donc toute aide est super. J'essaie de le faire via Javascript. C'est ce que j'ai jusqu'ici:
str = str.split(/,+|"[^"]+"/g);
Mais pour le moment, tout le contenu des guillemets est fractionné, ce qui est inexact .. .. Merci de votre aide.
Edit: OK, désolé, j’ai mal formulé la question. On me donne une chaîne, pas un tableau.
var str = 'a, b, c, "d, e, f", g, h';
Et je veux transformer that en un tableau utilisant quelque chose comme la fonction "split".
Voici ce que je ferais.
var str = 'a, b, c, "d, e, f", g, h';
var arr = str.match(/(".*?"|[^",\s]+)(?=\s*,|\s*$)/g);
/* will match:
(
".*?" 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]);
Cela fonctionne bien pour moi. (J'ai utilisé des points-virgules pour que le message d'alerte indique la différence entre les virgules ajoutées lors de la conversion du tableau en chaîne et les valeurs capturées.)
var str = 'a; b; c; "d; e; f"; g; h; "i"';
var array = str.match(/("[^"]*")|[^;]+/g);
alert(array);
Voici une fonction JavaScript pour le faire:
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;
}
Voici un non-regex qui suppose que les guillemets doubles viendront par paires:
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'])
Je sais que c'est un peu long, mais voici ce que je pense:
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);
En remarque, cela fonctionnera avec et sans les accolades au début et à la fin.
regex: /,(?=(?:(?:[^"]*"){2})*[^"]*$)/
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"
Référence lien suivant pour une explication: regexr.com/44u6o
Quelque chose comme une pile devrait faire l'affaire. Ici, j’utilise vaguement le marqueur booléen comme une pile (je ne fais que servir à cela).
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));
Cela prend un fichier csv ligne par ligne et crache un tableau avec des virgules dans les repères de parole intacts. s'il n'y a pas de marques de parole détectées, il suffit que .split (",") s comme d'habitude ... les probs pourraient remplacer cette seconde boucle par quelque chose, mais le travail est effectué tel quel.
function parse(str){
if(str.indexOf("\"")>-1){
var aInputSplit = str.split(",");
var aOutput = [];
//var adding = 0;
for(i=0;i<aInputSplit.length;i++){
if(aInputSplit[i].indexOf("\"")>-1){
var sWithCommas = aInputSplit[i];
for(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;
}
}
}else{
aOutput.Push(aInputSplit[i]);
}
}
return aOutput;
}else{
return str.split(",");
}
}
jsfiddle setting imageimage de sortie du code
Le code fonctionne si votre chaîne d'entrée est au format stringTocompare. Exécutez le code sur https://jsfiddle.net/ pour voir le résultat du paramétrage de fiddlejs . Veuillez vous reporter à la capture d'écran . Vous pouvez utiliser la fonction de partage pour le même code. dessous et ajuster le code en fonction de vos besoins . Supprimez les caractères gras ou Word avec in ** du code si vous ne souhaitez pas avoir de virgule après la scission join = attach ** + "," ** + actualString [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