3 Stimmen

Regex: Übereinstimmung mit einer Zeichenfolge, die Zahlen und Buchstaben enthält, aber nicht mit einer Zeichenfolge, die nur aus Zahlen besteht

Pregunta

Ich möchte in der Lage sein, eine einzige Regex (wenn möglich) zu verwenden, um zu verlangen, dass eine Zeichenfolge passt [A-Za-z0-9_] aber nicht zulässt:

  • Zeichenketten, die nur Zahlen oder/und Symbole enthalten.
  • Zeichenketten, die mit Symbolen beginnen oder enden
  • Mehrere Symbole nebeneinander

Gültig

  • test_0123
  • t0e1s2t3
  • 0123_test
  • te0_s1t23
  • t_t

Ungültig

  • t__t
  • ____
  • 01230123
  • _0123
  • _test
  • _test123
  • test_
  • test123_

Gründe für die Regeln

Der Zweck ist, Benutzernamen für eine Website zu filtern, an der ich arbeite. Ich habe mir die Regeln aus bestimmten Gründen zurechtgelegt.

  • Benutzernamen, die nur aus Zahlen und/oder Symbolen bestehen, können zu Problemen bei der Weiterleitung und bei Datenbankabfragen führen. Die Route für /users/#{id} ermöglicht id entweder die Benutzerkennung oder der Name des Benutzers sein. Namen und IDs sollten also nicht kollidieren können.

  • _test sieht seltsam aus, und ich glaube nicht, dass es sich um eine gültige Subdomain handelt, d. h. _test.example.com

  • Ich mag das Aussehen von t__t als Subdomäne, d.h. t__t.example.com

8voto

Amber Punkte 473552

Das entspricht genau dem, was Sie wollen:

/\A(?!_)(?:[a-z0-9]_?)*[a-z](?:_?[a-z0-9])*(?<!_)\z/i
  1. Mindestens ein alphabetisches Zeichen (die [a-z] in der Mitte).
  2. Beginnt oder endet nicht mit einem Unterstrich (die (?!_) y (?<!_) am Anfang und am Ende).
  3. Es können beliebig viele Zahlen, Buchstaben oder Unterstriche vor und nach dem Buchstaben stehen, aber jeder Unterstrich muss durch mindestens eine Zahl oder einen Buchstaben (den Rest) getrennt sein.

Bearbeiten: In der Tat, Sie brauchen wahrscheinlich nicht einmal die Lookahead/Lookbehinds aufgrund, wie der Rest der Regex funktioniert - die erste ?: ein Unterstrich erst nach einem alphanumerischen Zeichen zulässig ist, und der zweite ?: Parenthese lässt keinen Unterstrich zu, es sei denn, er steht vor einem alphanumerischen Zeichen:

/\A(?:[a-z0-9]_?)*[a-z](?:_?[a-z0-9])*\z/i

Sollte gut funktionieren.

2voto

Telemachus Punkte 18969

Ich bin sicher, dass Sie könnte all dies in einen regulären Ausdruck zu packen, aber es wird nicht einfach sein, und ich bin mir nicht sicher, warum ich darauf bestehe, dass es un regex. Warum nicht mehrere Durchgänge bei der Validierung verwenden? Wenn die Validierungsprüfungen beim Anlegen eines neuen Kontos durchgeführt werden, gibt es eigentlich keinen Grund, dies in eine Regex zu packen. (Das heißt, Sie haben es jeweils nur mit einem Element zu tun, nicht mit Hunderten oder Tausenden oder mehr. Ein paar Durchläufe über einen normal großen Benutzernamen sollte sehr wenig Zeit in Anspruch nehmen, würde ich denken.)

Zuerst wird abgelehnt, wenn der Name nicht mindestens eine Zahl enthält; dann wird abgelehnt, wenn der Name nicht mindestens einen Buchstaben enthält; dann wird geprüft, ob der Anfang und das Ende korrekt sind; usw. Jeder dieser Durchläufe könnte ein einfach zu lesender und leicht zu pflegender regulärer Ausdruck sein.

2voto

Sinan Taifour Punkte 9904

Worüber?

/^(?=[^_])([A-Za-z0-9]+_?)*[A-Za-z](_?[A-Za-z0-9]+)*$/

Sie verwendet keine Rückverweise.

Editer :

Erfolgreich für alle Ihre Testfälle. Ist Ruby-kompatibel.

1voto

Tim Punkte 8672

Dadurch wird "__" nicht blockiert, aber der Rest wird erhalten:

([A-Za-z]|[0-9][0-9_]*)([A-Za-z0-9]|_[A-Za-z0-9])*

Und hier ist das längere Formular, das alle Ihre Regeln enthält:

([A-Za-z]|([0-9]+(_[0-9]+)*([A-Za-z|_[A-Za-z])))([A-Za-z0-9]|_[A-Za-z0-9])*

verdammt, ist das hässlich. Ich werde mit Telemachus zustimmen, dass Sie wahrscheinlich nicht tun sollten, dies mit einem regex, obwohl es technisch möglich ist. regex ist oft ein Schmerz für die Wartung.

1voto

glenn mcdonald Punkte 14952

Die Frage fragt nach einem einzelnen regexp und impliziert, dass es ein regexp sein sollte, der passt zu was in Ordnung ist und von anderen beantwortet wurde. Aus Interesse stelle ich jedoch fest, dass es einfacher ist, diese Regeln direkt als Regexp anzugeben, der no übereinstimmen. D.h.:

x !~ /[^A-Za-z0-9_]|^_|_$|__|^\d+$/
  • keine anderen Zeichen als Buchstaben, Zahlen und _
  • kann nicht mit einem _ beginnen
  • kann nicht mit einem _ enden
  • kann nicht zwei _s in einer Reihe haben
  • können nicht alle Ziffern sein

Sie können es nicht auf diese Weise in einem Rails validates_format_of verwenden, aber Sie könnten es in eine validate-Methode für die Klasse setzen, und ich denke, Sie hätten viel bessere Chancen, auch in einem Monat oder einem Jahr noch zu verstehen, was Sie gemeint haben.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X