Comme austincheney souligne à juste titre, vous avez vraiment besoin pour analyser la chaîne du début à la fin si vous souhaitez gérer correctement cité des chaînes de caractères qui peut contenir des caractères d'échappement. Aussi, l'OP ne définit pas clairement ce qu'est un "CSV chaîne" est vraiment. Nous devons d'abord définir ce qui constitue un valide CSV chaîne et de ses valeurs.
Donnée: "CSV" Chaîne de Définition
Pour les fins de cette discussion, un "CSV" chaîne se compose de zéro ou plusieurs valeurs, où plusieurs valeurs sont séparées par une virgule. Chaque valeur peut consister en:
- Une double chaîne de caractères entre guillemets. (peut contenir sans échappement des apostrophes.)
- Une seule chaîne de caractères entre guillemets. (peut contenir sans échappement double guillemets.)
- Un non-chaîne entre guillemets. (ne peut PAS contenir des citations, des virgules ou des barres obliques inverses.)
- Une valeur vide. (Une tous les espaces de la valeur est considérée comme vide.)
Règles/Remarques:
- Des valeurs à la cote peuvent contenir des virgules.
- Des valeurs à la cote peut contenir des échappés-quoi que ce soit, par exemple,
'that\'s cool'
.
- Les valeurs contenant des citations, des virgules ou des barres obliques inverses doivent être indiqués.
- Les valeurs contenant des espaces avant ni après doivent être indiqués.
- La barre oblique inverse est retiré de tous:
\'
dans une seule des valeurs à la cote.
- La barre oblique inverse est retiré de tous:
\"
en double des valeurs à la cote.
- Non chaînes entre guillemets sont garnis de toute attaque et de fuite des espaces.
- La virgule de séparation peut avoir les espaces adjacents (qui est ignoré).
Trouver:
Une fonction JavaScript qui convertit valide CSV chaîne de caractères (tel que défini ci-dessus) dans un tableau de valeurs de chaîne.
Solution:
Les expressions régulières utilisées par cette solution sont complexes. Et (à mon humble avis) de tous les non-trivial regexes devraient être présentés en libre-mode d'espacement avec beaucoup de commentaires et de l'indentation. Malheureusement, JavaScript ne permet pas de libre-mode d'espacement. Ainsi, les expressions régulières mises en œuvre par cette solution sont d'abord présentés en natif syntaxe regex (exprimé à l'aide de Python est très pratique: r'''...'''
raw multi-ligne-syntaxe de la chaîne).
Premier ici est une expression régulière qui permet de vérifier que les CVS chaîne répond aux exigences ci-dessus:
Regex pour valider un "CSV chaîne":
re_valid = r"""
# Validate a CSV string having single, double or un-quoted values.
^ # Anchor to start of string.
\s* # Allow whitespace before value.
(?: # Group for value alternatives.
'[^'\\]*(?:\\[\S\s][^'\\]*)*' # Either Single quoted string,
| "[^"\\]*(?:\\[\S\s][^"\\]*)*" # or Double quoted string,
| [^,'"\s\\]*(?:\s+[^,'"\s\\]+)* # or Non-comma, non-quote stuff.
) # End group of value alternatives.
\s* # Allow whitespace after value.
(?: # Zero or more additional values
, # Values separated by a comma.
\s* # Allow whitespace before value.
(?: # Group for value alternatives.
'[^'\\]*(?:\\[\S\s][^'\\]*)*' # Either Single quoted string,
| "[^"\\]*(?:\\[\S\s][^"\\]*)*" # or Double quoted string,
| [^,'"\s\\]*(?:\s+[^,'"\s\\]+)* # or Non-comma, non-quote stuff.
) # End group of value alternatives.
\s* # Allow whitespace after value.
)* # Zero or more additional values
$ # Anchor to end of string.
"""
Si une chaîne correspond à ce qui précède regex, alors que la chaîne est valide CSV chaîne (selon les règles précédemment indiqué) et peuvent être analysées à l'aide de la suite de regex. La regex suivante est ensuite utilisé pour faire correspondre une valeur à partir d'un fichier CSV chaîne. Il est appliqué à plusieurs reprises jusqu'à ce que plus aucun des correspondances sont trouvées (et toutes les valeurs ont été analysés).
Regex pour analyser une valeur à partir du valide CSV chaîne:
re_value = r"""
# Match one value in valid CSV string.
(?!\s*$) # Don't match empty last value.
\s* # Strip whitespace before value.
(?: # Group for value alternatives.
'([^'\\]*(?:\\[\S\s][^'\\]*)*)' # Either $1: Single quoted string,
| "([^"\\]*(?:\\[\S\s][^"\\]*)*)" # or $2: Double quoted string,
| ([^,'"\s\\]*(?:\s+[^,'"\s\\]+)*) # or $3: Non-comma, non-quote stuff.
) # End group of value alternatives.
\s* # Strip whitespace after value.
(?:,|$) # Field ends on comma or EOS.
"""
Notez qu'il existe un cas particulier de la valeur que cette expression ne correspond pas à la dernière valeur lorsque celle-ci est vide. Ce spécial "vide dernière valeur" cas est testé pour et traitées par la fonction js qui suit.
Fonction JavaScript pour analyser CSV chaîne:
// Return array of string values, or NULL if CSV string not well formed.
function CSVtoArray(text) {
var re_valid = /^\s*(?:'[^'\\]*(?:\\[\S\s][^'\\]*)*'|"[^"\\]*(?:\\[\S\s][^"\\]*)*"|[^,'"\s\\]*(?:\s+[^,'"\s\\]+)*)\s*(?:,\s*(?:'[^'\\]*(?:\\[\S\s][^'\\]*)*'|"[^"\\]*(?:\\[\S\s][^"\\]*)*"|[^,'"\s\\]*(?:\s+[^,'"\s\\]+)*)\s*)*$/;
var re_value = /(?!\s*$)\s*(?:'([^'\\]*(?:\\[\S\s][^'\\]*)*)'|"([^"\\]*(?:\\[\S\s][^"\\]*)*)"|([^,'"\s\\]*(?:\s+[^,'"\s\\]+)*))\s*(?:,|$)/g;
// Return NULL if input string is not well formed CSV string.
if (!re_valid.test(text)) return null;
var a = []; // Initialize array to receive values.
text.replace(re_value, // "Walk" the string using replace with callback.
function(m0, m1, m2, m3) {
// Remove backslash from \' in single quoted values.
if (m1 !== undefined) a.push(m1.replace(/\\'/g, "'"));
// Remove backslash from \" in double quoted values.
else if (m2 !== undefined) a.push(m2.replace(/\\"/g, '"'));
else if (m3 !== undefined) a.push(m3);
return ''; // Return empty string.
});
// Handle special case of empty last value.
if (/,\s*$/.test(text)) a.push('');
return a;
};
Exemple d'entrée et de sortie:
Dans les exemples suivants, les accolades sont utilisées pour délimiter l' {result strings}
. (C'est pour aider à visualiser le leading/trailing spaces et les chaînes de longueur nulle.)
// Test 1: Test string from original question.
var test = "'string, duppi, du', 23, lala";
var a = CSVtoArray(test);
/* Array hes 3 elements:
a[0] = {string, duppi, du}
a[1] = {23}
a[2] = {lala} */
// Test 2: Empty CSV string.
var test = "";
var a = CSVtoArray(test);
/* Array hes 0 elements: */
// Test 3: CSV string with two empty values.
var test = ",";
var a = CSVtoArray(test);
/* Array hes 2 elements:
a[0] = {}
a[1] = {} */
// Test 4: Double quoted CSV string having single quoted values.
var test = "'one','two with escaped \' single quote', 'three, with, commas'";
var a = CSVtoArray(test);
/* Array hes 3 elements:
a[0] = {one}
a[1] = {two with escaped ' single quote}
a[2] = {three, with, commas} */
// Test 5: Single quoted CSV string having double quoted values.
var test = '"one","two with escaped \" double quote", "three, with, commas"';
var a = CSVtoArray(test);
/* Array hes 3 elements:
a[0] = {one}
a[1] = {two with escaped " double quote}
a[2] = {three, with, commas} */
// Test 6: CSV string with whitespace in and around empty and non-empty values.
var test = " one , 'two' , , ' four' ,, 'six ', ' seven ' , ";
var a = CSVtoArray(test);
/* Array hes 8 elements:
a[0] = {one}
a[1] = {two}
a[2] = {}
a[3] = { four}
a[4] = {}
a[5] = {six }
a[6] = { seven }
a[7] = {} */
Notes supplémentaires:
Cette solution nécessite que le CSV chaîne de l'être "valide". Par exemple, les valeurs non cotées ne peuvent pas contenir des barres obliques inverses ou des citations, par exemple, à la suite de CSV chaîne n'est PAS valide:
var invalid1 = "one, that's me!, escaped \, comma"
Ce n'est pas vraiment une limitation, car tout sous-chaîne peut être représentée sous la forme d'un simple ou double cité de la valeur. Notez également que cette solution ne représente qu'une définition possible pour: les "Valeurs Séparées par des Virgules".
Avertissement
2014-05-19 mise à Jour: La réponse ci-dessus ne fonctionne que pour un modèle très précis de CSV. Comme souligné à juste titre par la DG dans les commentaires, cette solution ne correspond PAS à la norme RFC 4180 définition de CSV et il ne rentre PAS en format MS Excel. Cette solution illustre simplement comment on peut analyser une ligne de l'entrée contient un mélange de types de chaînes, où les chaînes peuvent contenir échappé des citations et des virgules.
Edit: 2014-05-19: Ajout de l'avertissement.