JS-Regex zum Aufteilen nach Zeilen

78

Wie teilt man ein langes Stück Text in separate Zeilen auf? Warum gibt diese Zeile1 zweimal zurück?

/^(.*?)$/mg.exec('line1\r\nline2\r\n');

["line1", "line1"]

Ich habe den mehrzeiligen Modifikator aktiviert, um Anfang und Ende von Zeilen zu erstellen ^und $abzugleichen. Ich habe auch den globalen Modifikator aktiviert, um alle Zeilen zu erfassen .

Ich möchte einen Regex-Split verwenden und nicht, String.splitweil ich mich sowohl mit Linux- \nals auch mit Windows- \r\nZeilenenden befassen werde .

JoJo
quelle

Antworten:

146
arrayOfLines = lineString.match(/[^\r\n]+/g);

Wie Tim sagte, ist es sowohl das gesamte Match als auch das Capture. Es wird angezeigt regex.exec(string), dass die erste Übereinstimmung unabhängig vom globalen Modifikator gefunden string.match(regex)wird, wobei global berücksichtigt wird.

ReactiveRaven
quelle
9
Als Hinweis wird Tims mit leeren Zeilen übereinstimmen, während meine nicht. Entweder kann oder kann nicht wünschenswert sein.
ReactiveRaven
Alte Antwort, aber ich möchte sagen, dass der Grund für die execRückkehr bei der ersten Übereinstimmung darin besteht, dass sie für globale Regexe mehrmals aufgerufen werden soll, bis sie null zurückgibt, und die Regex Dinge wie lastIndexden Index speichert, bei dem die nächste beginnen soll Spiel.
iPherian
Versuchen Sie es "123\n\n1234".match(/[^\r\n]+/g);erwartet Array [ "123", "", "1234" ], aber Sie habenArray [ "123", "1234" ]
Seek kg
105

Verwenden

result = subject.split(/\r?\n/);

Ihre Regex wird line1zweimal zurückgegeben, da line1sowohl die gesamte Übereinstimmung als auch der Inhalt der ersten Erfassungsgruppe angezeigt werden.

Tim Pietzcker
quelle
4
Sie müssen die gFlagge verwenden und \rist auf einigen alten Apple-Maschinen eine gültige neue Zeile. Auch Unicode definiert \u2028, \u2029und die alte IBM Newline \u0085als Zeilenumbrüche. So /[\n\u0085\u2028\u2029]|\r\n?/gkümmert sich um alle Grenzfälle.
Mike Samuel
7
@ Mike: Bist du dir über die /gFlagge sicher ? Es ist nicht sinnvoll, eine Teilungsfunktion zu haben, die nur einmal geteilt wird, sofern nicht ausdrücklich anders angegeben. Und Jojo sagte, dass er nur mit Linux und Windows zu tun hat. Was kommt als nächstes, EBCDIC?
Tim Pietzcker
4
@ Mike: Nein, die /gFlagge ist nicht erforderlich. Sie können es hinzufügen, aber JavaScript ignoriert es einfach. Wie Tim sagte, besteht das Standardverhalten darin, so oft wie möglich zu teilen, aber Sie können das zweite Argument verwenden, um ein Maximum festzulegen.
Alan Moore
23
Was eine Newline ausmacht, ist noch schlimmer. Laut dem Unicode-Konsortium sollten wir immer verwenden (\r\n|[\n\v\f\r\x85\u2028\u2029]), egal auf welcher Plattform die Software ausgeführt wird oder woher die Daten stammen.
Alan Moore
@ Alan, ganz richtig. Das gFlag steuert, ob Erfassungsgruppen in der Ausgabe enthalten sind.
Mike Samuel
26

Ich gehe davon aus, dass das Folgende Zeilenumbrüche darstellt

  1. \ r gefolgt von \ n
  2. \ n gefolgt von \ r
  3. \ n allein anwesend
  4. Ich bin allein anwesend

Bitte verwende

var re=/\r\n|\n\r|\n|\r/g;

arrayofLines=lineString.replace(re,"\n").split("\n");

für ein Array aller Zeilen einschließlich der leeren.

ODER

Bitte verwende

arrayOfLines = lineString.match(/[^\r\n]+/g); 

Für ein Array nicht leerer Zeilen

Arup Hore
quelle
\ngefolgt von \rist kein einziger Zeilenumbruch
JLRishe
22

Noch einfacher Regex, der alle Zeilenendkombinationen verarbeitet, auch in derselben Datei gemischt, und auch leere Zeilen entfernt:

var lines = text.split(/[\r\n]+/g);

Mit Leerzeichen:

var lines = text.trim().split(/\s*[\r\n]+\s*/g);

Ciscoheat
quelle
1
Der erste entfernt leere Zeilen in der Mitte des Textes, jedoch nicht am Anfang oder am Ende. Das ist in Ordnung für meine Zwecke, ich möchte nur darauf hinweisen, dass jeder, der die Entfernung benötigt, konsistent ist.
Twm
6

Ersetzen Sie zuerst alle \r\ndurch \n, dann String.split .

Tim
quelle
Dies erfordert zwei Befehle. Kann es mit Regex in einem Befehl gemacht werden?
JoJo
2
@ JoJo: myString.replace(/\r\n/, "\n").split("\n")(es sei denn, Sie fragen wegen akademischen Interesses :))
Tim
'line1\r\nline2\r\n'.replace(/\r\n/, '\n').split('\n').without('');erzeugt eine falsche zweite Zelle:["line1", "line2\r"]
JoJo
@ JoJo: Entschuldigung, ich habe die /gFlagge für global vergessen ! Es sollte sein:myString.replace(/\r\n/g, "\n").split("\n")
Tim
3
@ Jojo: Dies ist kurz und bündig in einer Zeile :) Regexes sind nicht das Werkzeug für jeden Job. Sie können sehr mächtig sein, sollten aber nicht überall eingesetzt werden. Beachten Sie, dass replace ist ein regulärer Ausdruck.
Tim
0

http://jsfiddle.net/uq55en5o/

var lines = text.match(/^.*((\r\n|\n|\r)|$)/gm);

Ich habe so etwas gemacht. Über dem Link ist meine Geige.

Abhijit_Srikumar
quelle
Dadurch bleibt der Zeilentrenner am Ende.
Sean