Essayer :
public class Main {
public static void main(String[] args) {
String line = "foo,bar,c;qual=\"baz,blurb\",d;junk=\"quux,syzygy\"";
String[] tokens = line.split(",(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)", -1);
for(String t : tokens) {
System.out.println("> "+t);
}
}
}
Sortie :
> foo
> bar
> c;qual="baz,blurb"
> d;junk="quux,syzygy"
En d'autres termes : séparez la virgule uniquement si cette virgule a zéro, ou un nombre pair de guillemets devant elle.
Ou, un peu plus convivial pour les yeux :
public class Main {
public static void main(String[] args) {
String line = "foo,bar,c;qual=\"baz,blurb\",d;junk=\"quux,syzygy\"";
String otherThanQuote = " [^\"] ";
String quotedString = String.format(" \" %s* \" ", otherThanQuote);
String regex = String.format("(?x) "+ // activer les commentaires, ignorer les espaces blancs
", "+ // correspondre à une virgule
"(?= "+ // commencer une recherche positive en avant
" (?: "+ // démarrer le groupe non-capturant 1
" %s* "+ // correspondre à 'otherThanQuote' zéro ou plusieurs fois
" %s "+ // correspondre à 'quotedString'
" )* "+ // fin du groupe 1 et le répéter zéro ou plusieurs fois
" %s* "+ // correspondre à 'otherThanQuote'
" $ "+ // correspondre à la fin de la chaîne
") ", // arrêter la recherche positive en avant
otherThanQuote, quotedString, otherThanQuote);
String[] tokens = line.split(regex, -1);
for(String t : tokens) {
System.out.println("> "+t);
}
}
}
qui produit le même résultat que le premier exemple.
ÉDITER
Comme mentionné par @MikeFHay dans les commentaires :
Je préfère utiliser Guava's Splitter, car il a des valeurs par défaut plus raisonnables (voir la discussion ci-dessus sur les correspondances vides étant supprimées par String#split()
), donc j'ai fait :
Splitter.on(Pattern.compile(",(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)"))