2017-02-08 14 views
1

Ich möchte Erwähnungen an @Benutzernamen erfassen. Benutzernamen haben diese Regeln: (.) ​​Wie behebt man diesen @mention regex?

  • nur Kleinbuchstaben, Zahlen oder Punkte
  • nicht beginnen oder enden mit einem Punkt
  • nicht mehr als ein Punkt in einer Reihe (zB user..name ist nicht erlaubt, aber us.er.name ist)

So kam ich mit auf den Punkt:

/(?:^|\s)(@)(?!\.)(?!.*\.\.)(?!.*\.[\s|$])([a-z0-9\.]+)(?:\s|$)/gm; 

das bedeuten sollte:

Als ein komplettes Noob mit Regexes, war ich ziemlich glücklich zu sehen, wie dies mit einer langen, mehrzeiligen Testreihe funktionierte. Aber dann habe ich versucht, den einfachsten Test-String, wie:

@foo @bar I hate you both. 

In diesem Fall foo gefangen, aber bar nicht. Ich nehme an, dass, selbst wenn ich eine nicht-einfangende Gruppe benutze, @foo auch die folgenden Leerzeichen akzeptiert, so dass @bar bei (?:^|\s) fehlschlägt.

Wie soll ich diesen Regex bearbeiten, damit er funktioniert?

Bitte schlagen Sie nicht einen völlig anderen @ Mention Regex vor, ich kann sehr gut nach ihnen suchen, da es andere Fragen gibt. Ich möchte nur, dass das funktioniert und zu wissen, warum es nicht funktioniert.

+0

Was möchten Sie mit "@ foo @ bar" passieren? –

+0

@Shawn überhaupt keinen Haken, da muss ein Leerzeichen dazwischen sein. – natario

+0

Ihr RegEx funktioniert perfekt, wenn Sie Lookbehind verwenden ([Beispiel] (https://regex101.com/r/ypzKoJ/1)), aber ich bin sicher, dass Sie wissen, dass Javascript das nicht unterstützt. Am besten ist es, das Lookbehind in Lookahead- und Conditional-Anweisungen zu übersetzen. –

Antwort

2

Im Allgemeinen besteht das Problem hier darin, dass Sie eine Erfassungsgruppe für die Leerzeichen am Anfang und am Ende eines Worts verwenden. Dies bedeutet, dass diese Zeichen von weiteren RegEx-Vergleichen verwendet werden.

Dies ist, weil Sie tun: (?:...).

Stattdessen können Sie eine spezielle Klasse von Capture-Gruppen verwenden, die nicht die Zeichen verbraucht, die so genannten Look-Ahead: (?=...)

In RegEx gibt es Lookbehind und Lookahead, die vor überprüft und nach der RegEx ist. Die perfekte Antwort auf Ihre Frage würde beide Lookbehind für den Anfang der Zeichenfolge (?<=^|\s) und Lookahead für das Ende der Zeichenfolge (?=\s|$) verwenden. Leider wird Lookbehind in Javascript nicht unterstützt, aber für Ihre speziellen Bedürfnisse können wir das irgendwie umgehen.

Wenn wir sicherstellen, dass das nachstehende Leerzeichen am Ende eines Benutzernamens NICHT erfasst wird, kann es zur Übereinstimmung mit der Erfassungsgruppe verwendet werden, die Sie am Anfang der RegEx definiert haben. Hier ist der Code:

(?:^|\s)(@)(?!\.)(?!\S*\.\.)(?!\S*\.[\s|$])([a-z0-9\.]+)(?=\s|$) 

Hinweis alles ist fast gleich, mit Ausnahme des ‚=‘ im letzten Abschnitt, und ‚\ S‘ im Abschnitt ‚nicht mit einem Punkt enden‘ und ‚nicht mit zwei benachbarten Punkte ', die Sie unten in den Kommentaren gefangen haben.

Ergebnisse können here gefunden werden. Leider gibt dies die vollständige Übereinstimmung mit dem Leerzeichen für "@bar" zurück, aber die Untergruppen dieses Matches sehen immer noch gut aus.

Lassen Sie mich wissen, ob dies hilft!

+0

Danke. Ich werde es morgen anschauen, afk jetzt. Sollte die Bedingung "nicht mit einem Punkt endend" neu geschrieben werden? Seitlicher Leerzeichen wird nicht mehr erfasst. Ich meine (?!. * \. [\ S | $]) – natario

+0

Guter Fang, du musst das in '(?! \ S * \. [\ S | $])' 'ändern, wo es mit einer beliebigen Zahl übereinstimmt Zeichen, die kein Leerzeichen sind, sonst "@foo @bar". finde keine Benutzernamen. Ich werde meine Antwort und mein Beispiel aktualisieren. –

+0

Sie müssen auch '(?!. * \. \.)' Von "ohne zwei benachbarte Punkte" zu '(?! \ S * \. \.)' –

0

wird diese regexp die Arbeit machen:

@[0-9a-z](\.?[0-9a-z])* 

wie im folgenden demo gesehen.

Verwandte Themen