Question

Je dois prendre en charge les expressions exactes (entre guillemets) dans une liste de termes séparés par des espaces. Ainsi, diviser la chaîne respective par le caractère espace ne suffit plus.

Exemple:

input : 'foo bar "lorem ipsum" baz'
output: ['foo', 'bar', 'lorem ipsum', 'baz']

Je me demande si cela pourrait être réalisé avec un seul RegEx, plutôt que d'effectuer des opérations complexes d'analyse ou de scission / rejoin.

Toute aide serait grandement appréciée!

Était-ce utile?

La solution

var str = 'foo bar "lorem ipsum" baz';  
var results = str.match(/("[^"]+"|[^"\s]+)/g);

... renvoie le tableau que vous recherchez.
Notez cependant:

  • Les guillemets sont inclus, ils peuvent donc être supprimés avec replace (/ ^ "([^"] +) ") $ /," $ 1 ") sur les résultats.
  • Les espaces entre les guillemets resteront intacts. Donc, s'il y a trois espaces entre lorem et ipsum , ils seront dans le résultat. Vous pouvez résoudre ce problème en exécutant replace (/ \ s + /, "") sur les résultats.
  • S'il n'y a pas de fermeture " après ipsum (c.-à-d. une phrase mal citée), vous obtiendrez: ['foo', 'bar ',' lorem ',' ipsum ',' baz ']

Autres conseils

Essayez ceci:

var input = 'foo bar "lorem ipsum" baz';
var R =  /(\w|\s)*\w(?=")|\w+/g;
var output = input.match(R);

output is ["foo", "bar", "lorem ipsum", "baz"]

Notez qu'il n'y a pas de guillemets doubles supplémentaires autour de lorem ipsum

Bien que cela suppose que l'entrée a les guillemets doubles au bon endroit:

var input2 = 'foo bar lorem ipsum" baz'; var output2 = input2.match(R);
var input3 = 'foo bar "lorem ipsum baz'; var output3 = input3.match(R);

output2 is ["foo bar lorem ipsum", "baz"]
output3 is ["foo", "bar", "lorem", "ipsum", "baz"]

Et ne gérera pas les guillemets doubles échappés (est-ce un problème?):

var input4 = 'foo b\"ar  bar\" \"bar "lorem ipsum" baz';
var output4 = input4.match(R);

output4 is  ["foo b", "ar bar", "bar", "lorem ipsum", "baz"]

que diriez-vous,

output = /(".+?"|\w+)/g.exec(input)

puis effectuez un transfert sur la sortie pour perdre les guillemets.

alternativement,

output = /"(.+?)"|(\w+)/g.exec(input)

puis effectuez une sortie n pour perdre les captures vides.

Merci beaucoup pour les réponses rapides!

Voici un résumé des options pour la postérité:

var input = 'foo bar "lorem ipsum" baz';

output = input.match(/("[^"]+"|[^"\s]+)/g);
output = input.match(/"[^"]*"|\w+/g);
output = input.match(/("[^"]*")|([^\s"]+)/g)
output = /(".+?"|\w+)/g.exec(input);
output = /"(.+?)"|(\w+)/g.exec(input);

Pour mémoire, voici l'abomination que j'avais proposée:

var input = 'foo bar "lorem ipsum" "dolor sit amet" baz';
var terms = input.split(" ");

var items = [];
var buffer = [];
for(var i = 0; i < terms.length; i++) {
    if(terms[i].indexOf('"') != -1) { // outer phrase fragment -- N.B.: assumes quote is either first or last character
        if(buffer.length === 0) { // beginning of phrase
            //console.log("start:", terms[i]);
            buffer.push(terms[i].substr(1));
        } else { // end of phrase
            //console.log("end:", terms[i]);
            buffer.push(terms[i].substr(0, terms[i].length - 1));
            items.push(buffer.join(" "));
            buffer = [];
        }
    } else if(buffer.length != 0) { // inner phrase fragment
        //console.log("cont'd:", terms[i]);
        buffer.push(terms[i]);
    } else { // individual term
        //console.log("standalone:", terms[i]);
        items.push(terms[i]);
    }
    //console.log(items, "\n", buffer);
}
items = items.concat(buffer);

//console.log(items);
'foo bar "lorem ipsum" baz'.match(/"[^"]*"|\w+/g);

les guillemets englobants sont inclus si

Une expression régulière simple suffira mais laissera les guillemets. par exemple

'foo bar "lorem ipsum" baz'.match(/("[^"]*")|([^\s"]+)/g)
output:   ['foo', 'bar', '"lorem ipsum"', 'baz']

edit: battu par shyamsundar, désolé pour la double réponse

Une solution facile à comprendre et une solution générale. Fonctionne pour tous les délimiteurs et les personnages "rejoindre". Prend également en charge les mots 'joints' d’une longueur supérieure à deux mots, c’est-à-dire des listes telles que

"Bonjour, je m'appelle 'jon delaware smith fred', j'ai un 'nom long' '" ....

Un peu comme la réponse de AC mais un peu plus net ...

function split(input, delimiter, joiner){
    var output = [];
    var joint = [];
    input.split(delimiter).forEach(function(element){
        if (joint.length > 0 && element.indexOf(joiner) === element.length - 1)
        {
            output.push(joint.join(delimiter) + delimiter + element);
            joint = [];
        }
        if (joint.length > 0 || element.indexOf(joiner) === 0)
        {
            joint.push(element);
        }
        if (joint.length === 0 && element.indexOf(joiner) !== element.length - 1)
        {
            output.push(element);
            joint = [];
        }
    });
    return output;
  }

Si vous vous demandez comment créer vous-même la regex, consultez Expresso ( Expresso lien ). C'est un excellent outil pour apprendre à créer des expressions régulières afin que vous sachiez ce que signifie la syntaxe.

Une fois que vous avez créé votre propre expression, vous pouvez y effectuer un .match .

Cela peut être une réponse très tardive, mais je suis intéressé à répondre

([\w]+|\"[\w\s]+\")

http://regex101.com/r/dZ1vT6/72

Exemple javascript pur

 'The rain in "SPAIN stays" mainly in the plain'.match(/[\w]+|\"[\w\s]+\"/g)

Sorties:

["The", "rain", "in", ""SPAIN stays"", "mainly", "in", "the", "plain"]

Solution ES6 prenant en charge:

  • Séparer par espace sauf les guillemets
  • Suppression des guillemets mais pas des guillemets d'échappement antislash
  • citation échappée devient citation

Code:

input.match(/\\?.|^$/g).reduce((p, c) => {
        if(c === '"'){
            p.quote ^= 1;
        }else if(!p.quote && c === ' '){
            p.a.push('');
        }else{
            p.a[p.a.length-1] += c.replace(/\\(.)/,"$1");
        }
        return  p;
    }, {a: ['']}).a

Sortie:

[ 'foo', 'bar', 'lorem ipsum', 'baz' ]
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top