Unterschied zwischen \ A \ z und ^ $ in regulären Ruby-Ausdrücken

196

In der Dokumentation habe ich gelesen:

Verwenden Sie \ A und \ z, um den Anfang und das Ende der Zeichenfolge abzugleichen, ^ und $ stimmen mit dem Anfang / Ende einer Zeile überein.

Ich werde einen regulären Ausdruck anwenden, um den vom Benutzer übermittelten Benutzernamen (oder die gleiche E-Mail-Adresse) zu überprüfen. Mit welchem ​​Ausdruck soll ich validates_format_ofim Modell verwenden? Ich kann den Unterschied nicht verstehen: Ich habe immer ^ und $ ...

Collimarco
quelle

Antworten:

226

Wenn Sie zur Validierung auf den regulären Ausdruck angewiesen sind, möchten Sie immer \Aund verwenden \z. ^und $wird nur bis zu einem Zeilenumbruchzeichen übereinstimmen, was bedeutet, dass sie eine E-Mail wie verwenden [email protected]\n<script>dangerous_stuff();</script>und sie trotzdem validieren lassen können, da der reguläre Ausdruck nur alles vor dem sieht \n.

Meine Empfehlung wäre, vorher nur neue Zeilen von einem Benutzernamen oder einer E-Mail zu entfernen, da es so gut wie keinen legitimen Grund dafür gibt. Dann können Sie \A \zentweder oder verwenden ^ $.

Luke
quelle
13
@ Ragmaanir ist richtig, es sollte mit kleinen Buchstaben \zstatt sein \Z!
Petr
10
+1 Danke! Obwohl ich Ihrer Empfehlung nicht zustimmen müsste: A) Fügen Sie keine unnötige Arbeit / Verarbeitung hinzu, wenn es einen geeigneten Sammelbegriff gibt, und B) insbesondere nicht, wenn Sie damit faul bleiben können, zwischen den beiden zu unterscheiden. Sie sind möglicherweise nicht immer in der Lage, Zeichenfolgen zu manipulieren, sondern nur Regex. Legen Sie also die richtige Zeichenfolge fest und kennen Sie den Unterschied!
Dooleyo
1
Ich habe das Beispiel mit gefährlichen Dingen nicht verstanden, da in beiden Fällen gefährliche Dinge in die Zeichenfolge aufgenommen werden könnten. Mit oder ohne neue Zeilen wäre dies ein Exploit, der mit HTML-Desinfektion und -Validierung behoben werden sollte.
Jayr Motta
2
@ JayrMotta Was die Demonstration zeigt, ist, dass das gefährliche Zeug Ihre gesamte Regex-Prüfung vollständig umgehen würde . Selbst wenn Sie in Ihrem regulären Ausdruck nach gefährlichen Dingen suchen würden, würde dies umgangen, wenn Sie $stattdessen nach "Ende der Zeichenfolge" suchen würden \z.
Doktor Blue
177

Laut Pickaxe :

^ Entspricht dem Zeilenanfang.

$ Entspricht dem Ende einer Zeile.

\A Entspricht dem Anfang der Zeichenfolge.

\z Entspricht dem Ende der Zeichenfolge.

\Z Entspricht dem Ende der Zeichenfolge, es sei denn, die Zeichenfolge endet mit einem "\n". In diesem Fall stimmt sie kurz vor dem Zeichenfolge überein "\n".

Verwenden Sie also \AKleinbuchstaben \z. Wenn Sie \Zjemanden verwenden , könnte sich ein Zeilenumbruchzeichen einschleichen. Dies ist meiner Meinung nach nicht gefährlich, könnte aber Algorithmen vermasseln, die davon ausgehen, dass die Zeichenfolge kein Leerzeichen enthält. Abhängig von Ihren Einschränkungen hinsichtlich Regex und Zeichenfolgenlänge kann jemand einen unsichtbaren Namen mit nur einem Zeilenumbruchzeichen verwenden.

Die JavaScript-Implementierung von Regex wird \Aals Literal 'A'( ref ) behandelt. Also pass auf dich auf und teste.

Ragmaanir
quelle
16

Der Anfang und das Ende einer Zeichenfolge müssen nicht unbedingt mit dem Anfang und dem Ende einer Zeile identisch sein. Stellen Sie sich vor, Sie hätten Folgendes als Testzeichenfolge verwendet:

mein
Name
ist
Andrew

Beachten Sie, dass die Zeichenfolge hat viele Linien in ihm - das ^und $Zeichen können Sie den Anfang und das Ende dieser Zeilen entsprechen (im Wesentlichen die Behandlung von \nZeichen als Trennzeichen) , während \Aund \Zermöglicht es Ihnen , den Anfang und das Ende des gesamten Strings entsprechen.

Andrew Hare
quelle
1
Beste Antwort meiner Meinung nach. "Im Grunde genommen das Zeichen \ n als Delimeter behandeln" hat mir wirklich geholfen zu verstehen, danke.
Flyout91
11

Unterschied durch Beispiel

  1. /^foo$/stimmt mit einer der folgenden /\Afoo\z/Aussagen überein, nicht:
whatever1
foo
whatever2
foo
whatever2
whatever1
foo
  1. /^foo$/und /\Afoo\z/alle stimmen mit folgenden überein:
foo
Chun Yang
quelle