134 votes

Regex pour le découpage d'une chaîne à l'aide de l'espace lorsqu'il n'est pas entouré par des guillemets simples ou doubles

Je suis nouveau sur les expressions régulières et vous remercie de votre aide. Je suis en train de mettre sur pied une expression qui va diviser l'exemple de la chaîne à l'aide de tous les espaces qui ne sont pas entourés par des guillemets simples ou doubles. Ma dernière tentative ressemble à ceci: (?!") et n'est pas assez de travail. C'est la division de l'espace avant la citation.

Exemple d'entrée:

This is a string that "will be" highlighted when your 'regular expression' matches something.

Sortie désirée:

This
is
a
string
that
will be
highlighted
when
your
regular expression
matches
something.

Notez que "will be" et 'regular expression' maintenir l'espace entre les mots.

280voto

Jan Goyvaerts Points 10402

Je ne comprends pas pourquoi tous les autres sont de proposer un tel complexe d'expressions régulières ou longues code. Essentiellement, vous voulez prendre deux sortes de choses à partir de votre chaîne: les séquences de caractères qui ne sont pas des espaces ou des citations, et des séquences de caractères qui commence et se termine avec une citation sans guillemets entre les deux, pour les deux types de guillemets. Vous pouvez facilement faire correspondre ces choses avec cette expression régulière:

[^\s"']+|"([^"]*)"|'([^']*)'

J'ai ajouté les captures de groupes parce que vous ne voulez pas les guillemets dans la liste.

Ce code Java génère la liste, l'ajout de la capture d'un groupe si elle correspond à exclure les citations, et l'ajout de l'ensemble de la correspondance de la regex si la capture d'un groupe n'a pas de match (non coté mot a été apparié).

List<String> matchList = new ArrayList<String>();
Pattern regex = Pattern.compile("[^\\s\"']+|\"([^\"]*)\"|'([^']*)'");
Matcher regexMatcher = regex.matcher(subjectString);
while (regexMatcher.find()) {
    if (regexMatcher.group(1) != null) {
        // Add double-quoted string without the quotes
        matchList.add(regexMatcher.group(1));
    } else if (regexMatcher.group(2) != null) {
        // Add single-quoted string without the quotes
        matchList.add(regexMatcher.group(2));
    } else {
        // Add unquoted word
        matchList.add(regexMatcher.group());
    }
} 

Si vous ne me dérange pas d'avoir les guillemets dans la liste retournée, vous pouvez utiliser un code bien plus simple:

List<String> matchList = new ArrayList<String>();
Pattern regex = Pattern.compile("[^\\s\"']+|\"[^\"]*\"|'[^']*'");
Matcher regexMatcher = regex.matcher(subjectString);
while (regexMatcher.find()) {
    matchList.add(regexMatcher.group());
} 

19voto

Jay Points 20373

Il y a plusieurs questions sur StackOverflow qui couvrent cette même question dans divers contextes à l'aide d'expressions régulières. Par exemple:

Mise à JOUR: Exemple de regex pour gérer seul et chaînes entre guillemets doubles. Ref: Comment puis-je diviser sur une chaîne à l'exception de l'intérieur des guillemets?

m/('.*?'|".*?"|\S+)/g

Testé avec un rapide extrait de code Perl et le résultat a été reproduit ci-dessous. Fonctionne également pour les cordes à vide ou un espace chaînes uniquement si ils sont entre guillemets (pas sûr si c'est souhaité ou pas).

This
is
a
string
that
"will be"
highlighted
when
your
'regular expression'
matches
something.

Notez que cela n'inclure la citation personnages eux-mêmes dans les paires de valeurs, si vous pouvez le retirer avec une chaîne de remplacer ou de modifier la regex de ne pas les inclure. Je vais laisser ça comme un exercice pour le lecteur ou l'autre affiche pour l'instant, comme à 2h du matin est trop tard pour être de jouer avec des expressions régulières plus ;)

6voto

mcrumley Points 3551

Si vous souhaitez autoriser échappé à des citations à l'intérieur de la chaîne, vous pouvez utiliser quelque chose comme ceci:

(?:(['"])(.*?)(?<!\\)(?>\\\\)*\1|([^\s]+))

Ces chaînes seront le groupe 2, unique non cotées mots seront le groupe 3.

Vous pouvez l'essayer sur des chaînes différentes ici: http://www.fileformat.info/tool/regex.htm ou http://gskinner.com/RegExr/

3voto

iRon Points 41

La regex par Jan Goyvaerts est la meilleure solution que j'ai trouvé jusqu'à présent, mais crée aussi vide (null) correspond à, ce qui il exclut dans son programme. Ces vides correspond également apparaître de regex testeurs (par ex. rubular.com). Si vous tournez la recherche arround (premier regard pour la cité des parties et que l'espace qui sépare les mots), alors vous pourriez le faire en une seule fois avec:

("[^"]*"|'[^']*'|[\S]+)+

2voto

(?<!\G".{0,99999})\s|(?<=\G".{0,99999}")\s

Cela va correspondre à l'espace qui n'est pas entouré par des guillemets. J'ai utiliser min,max {0,99999}, car Java ne supporte pas * et + dans lookbehind.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X