Frage

Ich muß genaue Sätze (in Anführungszeichen) in einer ansonsten durch Leerzeichen getrennte Liste von Begriffen unterstützen. Somit wird durch die Raum-Zeichen der jeweilige Zeichenfolge Aufspaltung ist nicht mehr ausreichend.

Beispiel:

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

Ich frage mich, ob dies mit einem einzigen RegEx erreicht werden könnte, anstatt komplex Parsing oder Split-and-rejoin Operationen durchführen.

Jede Hilfe wäre sehr geschätzt werden!

War es hilfreich?

Lösung

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

... gibt das Array Sie suchen.
Beachten Sie jedoch:

  • Bounding Zitate enthalten sind, können so mit replace(/^"([^"]+)"$/,"$1") auf den Ergebnissen entfernt werden.
  • Räume zwischen den Anführungszeichen wird intakt bleiben. Also, wenn es drei Räume zwischen lorem und ipsum, werden sie in der Folge sein. Sie können dieses Problem beheben, indem replace(/\s+/," ") auf den Ergebnissen ausgeführt wird.
  • Wenn es keine Schließung " nach ipsum ist (das heißt ein falsch zitierte Satz) Sie werden am Ende mit: ['foo', 'bar', 'lorem', 'ipsum', 'baz']

Andere Tipps

Versuchen Sie folgendes:

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"]

Hinweis: Es gibt keine zusätzlichen doppelte Anführungszeichen um Lorem ipsum

Auch wenn es übernimmt die Eingabe die doppelten Anführungszeichen in der richtigen Stelle hat:

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"]

Und wird nicht doppelte Anführungszeichen entgangen Griff (ist das ein Problem?):

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"]

Wie wäre es,

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

Sie dann einen Pass auf Ausgabe, die Anführungszeichen zu verlieren.

abwechselnd,

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

dann einen Pass n Ausgang tun, um die leeren Aufnahmen zu verlieren.

Vielen Dank für die schnellen Antworten!

Hier ist eine Zusammenfassung der Optionen, für die Nachwelt:

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);

Für die Aufzeichnung, hier ist der Gräuel ich gekommen war:

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);

die Begrenzungs Anführungszeichen erhalten, obwohl

enthalten

Ein einfacher regulärer Ausdruck wird tun, aber die Anführungszeichen lassen. z.

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

edit: geschlagen, um es von Shyamsundar, sorry für die doppelte Antwort

Eines, das zu verstehen und eine allgemeine Lösung einfach ist. Funktioniert für alle Trennzeichen und ‚nachziehen‘ Zeichen. Auch unterstützt ‚verbunden‘ Worte, die mehr als zwei Worte lang .... also Listen wie

sind

"hello my name is 'jon delaware smith fred' I have a 'long name'" ....

Ein bisschen wie die Antwort von AC aber etwas sauberen ...

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;
  }

Wenn Sie nur fragen, wie die Regex selbst zu bauen, möchten Sie vielleicht prüfen, Expresso ( Expresso Link ). Es ist ein großes Werkzeug zu lernen, wie man reguläre Ausdrücke zu bauen, so dass Sie wissen, was die Syntax bedeutet.

Wenn Sie Ihren eigenen Ausdruck erstellt haben, dann können Sie eine .match darauf ausführen.

Dies könnte eine sehr späte Antwort, aber ich bin an der Beantwortung

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

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

Reines Javascript Beispiel

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

Ausgänge:

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

ES6 Lösung unterstützt:

  • Split durch Raum mit Ausnahme in Anführungszeichen
  • Entfernen von Anführungszeichen, aber nicht für Backslash Anführungszeichen stehen
  • Entkommen Zitat worden Zitat

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

Ausgabe:

[ 'foo', 'bar', 'lorem ipsum', 'baz' ]
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top