2009-06-10 7 views
2

Hey Leute. Ich kämpfe mit einem regulären Ausdruck, der die Eingabe in einem Textfeld "Einzelseite/Seitenbereich" abbildet, was bedeutet, dass der Benutzer entweder eine einzelne Ganzzahl oder einen ganzzahligen Bereich im Format [lowerBound] - [upperBound] eingeben kann. Zum Beispiel:Regulärer Ausdruck, der einer einzelnen Seite oder einem Seitenbereich entspricht?


  • 11: Spiel
  • 2-9:: Abgleichung
  • 2a: kein Spiel
  • 19-:
  • 2 Spiel kein Spiel

Ist dies mit einem Regex möglich?

Bonus

  • 9-2: kein Spiel

Vielen Dank im Voraus.

Antwort

9

Wie Bryan sagt, dass der Vergleich zweier Zahlen nicht etwas ist, für das reguläre Ausdrücke gedacht sind. Wenn Sie nach dem Bonus-Fall suchen möchten, sollten Sie dies außerhalb des regulären Ausdrucks tun.

/^(\d+)(?:-(\d+))?$/ && $1 < $2; 

aber sagen, dass die meisten "reguläre Ausdrücke" Motoren sind nicht wirklich regular, so (zum Beispiel) ist es möglich, in Perl 5:

m{      # /../ is shorthand for m/../ 
    \A     # beginning of string 
    (\d+)    # first number 
    (?:-    # a non-capturing group starting with '-'... 
     (\d+)   #  second number 
     (?(?{$1>=$2}) #  if first number is >= second number 
      (?!))  #   fail this match 
    )?     # ...this group is optional 
    \Z     # end of string 
}x      # /x tells Perl to allow spaces and comments inside regex 

Oder /^(\d+)(?:-(\d+)(?:(?{$1>=$2})(?!)))?$/ kurz. Getestet in Perl 5.6.1, 5.8.8 und 5.10.0.


Passend der extended definition of ranges dass Lee schon sagt,

/^\s* 
    (\d+) (?:\s*-\s* (\d+))? 
    (?:\s*,\s* (\d+) (?:\s*-\s* (\d+))?)* 
\s*$/x 

einige Perl 5.10 Funktionen verwenden, ist es sogar möglich ist, um sicherzustellen, dass die Zahlen gut bestellt:

m{ 
    \A\s*        # start of string, spaces 
    (?{{$min = 0}})     # initialize min := 0 
    (?&RANGE) (?:\s*,\s* (?&RANGE))* # a range, many (comma, range) 
    \s*\Z        # spaces, end of string 

    (?(DEFINE)       # define the named groups: 
     (?<NUMBER>      # number := 
      (\d*)      #  a sequence of digits 
      (?(?{$min < $^N})   #  if this number is greater than min 
       (?{{$min = $^N}})  #  then update min 
       | (?!)))    #  else fail 
     (?<RANGE>      # range := 
      (?&NUMBER)     #  a number 
      (?:\s*-\s* (?&NUMBER))?)) #  maybe a hyphen and another number 
}x 
+0

Warum sagen Leute nun, dass Regexes nicht lesbar sind? Das sagt deutlich "Aardvarks sind schmackhaft" in Martian. –

+0

Ich habe vergessen zu schreiben, dass die erste Option viel besser ist als die zweite - ich werde es hier in diesem Kommentar sagen. Die zweite Option ist jedoch gut lesbar, wenn sie gut eingerückt und kommentiert ist. Die komprimierte Version ist nicht lesbar, aber auch viele Einzeiler in jeder Sprache./x ist ein guter Stil: In der Tat glaube ich, dass Perl 6 Regeln (Name gewählt als "regex" ist nicht mehr wirklich genau) sind/x standardmäßig. – ephemient

+0

Während ich glaube/x in Perl entstanden ist, hat Ruby das gleiche, Python hat re.X = re.VERBOSE, Java hat java.util.regex.Pattern.COMMENTS, .NET hat System.Text.RegularExpressions.RegexOptions.IgnorePatternWhitespace, und so weiter. Ich weiß nicht, warum diese Funktion nicht so oft gelobt wird wie sie sein sollte. – ephemient

3

Dies funktioniert für alle Testfälle:

^\d+(?:-\d+)?$ 

EDIT: Mit Ausnahme des letzten Testfall (9-2). Zu überprüfen, dass der zweite Wert größer als der erste Wert ist, ist für reguläre Ausdrücke nicht vorgesehen.

3
/^(\d+)(-(\d+))?/ 

wenn in Perl können Sie einfach

überprüfen
if $1 <= $3 
+0

+1 für einen Vorschlag zur Überprüfung der Bereich Werte sind richtig geordnet. – Bryan

3

Dies entspricht eine einzelne ganze Zahl oder einen Bereich und erfasst die Nummer (n) als submatches für die spätere Verwendung:

/^(\d+)(?:-(\d+))?$/ 
1

Seit Ich bin ein Tester, ich war glücklich, eine Liste von Testfällen zu sehen, die als Spezifikation verwendet wurden.Der Vollständigkeit halber möchte ich die folgenden Testfälle hinzu:

  • 2 - 9: Spiel
  • 2 -9: Spiel
  • -1-9: kein Spiel
  • 2- 9 entsprechen

Auch ein einzelner Seiten- oder Seitenbereich ist ein wenig vereinfachend. Ich würde diese zusätzlichen Testfälle unterstützt:

  • 1,3: Spiel
  • 1-5,13: match
  • 1-5,13-23: Spiel
  • 1,13-23 : match
  • usw.
+0

Es hat so lange gedauert, all diese ausgezeichneten Antworten zu sehen, denn ich war in einem Meeting über diese Website, auf der viele Ihrer Testfälle als mögliche Bedürfnisse aufgezogen wurden, besonders das "#, # - #" Szenario. Zuerst dachte ich nicht, dass das notwendig wäre, aber ich bin kein Tester :-) +1, und danke. –

Verwandte Themen