Warum funktioniert der Bereich [01-12] nicht wie erwartet?
91
Ich versuche, das Bereichsmuster [01-12]in Regex so zu verwenden, dass es mit zweistelligen mm übereinstimmt, aber dies funktioniert nicht wie erwartet.
Sie stimmen mit Zeichen überein , nicht mit Zeichenfolgen . Grundsätzlich stimmen Sie mit 0, 1 zu 1 und 2 überein (dh 0, 1 und 2). Beachten Sie Folgendes: [a-z0-9]Dies entspricht allen Kleinbuchstaben und allen Ziffern, jedoch nur als einzelnes Zeichen.
Lasse V. Karlsen
fwiw Ich habe ein Javascript-Tool erstellt, das aus zwei Eingaben (min / max) einen hochoptimierten regulären Ausdruck erstellt. github.com/jonschlinkert/to-regex-range
jonschlinkert
0 [1-9] | 1 [0-2] -> 0 | 1 | 2 -> [] s in einem regulären Ausdruck bezeichnen eine Zeichenklasse. Wenn keine Bereiche angegeben sind, wird implizit jedes Zeichen angezeigt.
Badri Gs
Müssen Sie es mit reinem Regex abgleichen? Wenn nicht, können Sie: 1.) einfach das \d+Muster verwenden, 2.) die übereinstimmenden Zeichenfolgen in Zahlen in Ihrem Code konvertieren. und dann 3.) überprüfen Sie den Nummernkreis wie if(num >= 0 && num <= 12){ /*do something*/ }. Es ist so viel schneller und flexibler.
Acegs
Antworten:
192
Sie scheinen falsch verstanden zu haben, wie die Definition von Zeichenklassen in Regex funktioniert.
Um eine der Saiten zu entsprechen 01, 02, 03, 04, 05, 06, 07, 08, 09, 10, 11, oder 12, so etwas wie dies funktioniert:
Numerische Bereiche (viele Beispiele für übereinstimmende Zeichenfolgen, die als numerische Bereiche interpretiert werden)
Erläuterung
Eine Zeichenklasse selbst versucht, ein und genau ein Zeichen aus der Eingabezeichenfolge abzugleichen. [01-12]tatsächlich definiert [012], eine Zeichenklasse , das ein Zeichen aus dem Eingang gegen keines der 3 Zeichen übereinstimmt 0, 1oder 2.
Die -Bereichsdefinition reicht von 1bis 1, einschließlich just 1. Auf der anderen Seite, so etwas wie [1-9]beinhaltet 1, 2, 3, 4, 5, 6, 7, 8, 9.
Anfänger machen oft die Fehler, Dinge wie zu definieren [this|that]. Das "funktioniert" nicht. Dieser Zeichendefinition definiert [this|a], dh es ist ein Zeichen aus dem Eingangs gegen keines von 6 Zeichen entspricht in t, h, i, s, |oder a. Mehr als wahrscheinlich (this|that)ist das, was beabsichtigt ist.
So ist es jetzt offensichtlich, dass ein Muster wie between [24-48] hours"nicht funktioniert". Die Zeichenklasse entspricht in diesem Fall [248].
Das heißt, -in einer Zeichenklasse definiert die Definition keinen numerischen Bereich im Muster. Regex-Engines "verstehen" Zahlen im Muster nicht wirklich, mit Ausnahme der Syntax endlicher Wiederholungen (z. B. a{3,5}Übereinstimmungen zwischen 3 und 5 a).
Die Bereichsdefinition verwendet stattdessen die ASCII / Unicode-Codierung der Zeichen, um Bereiche zu definieren. Das Zeichen 0wird in ASCII als Dezimalzahl 48 codiert. 9Somit enthält die Zeichendefinition [0-9]alle Zeichen, deren Werte in der Codierung zwischen 48 und 57 liegen. Vielmehr vernünftig, durch Design , das sind die Zeichen 0, 1, ..., 9.
Für mich suchte ich monatelang ohne Präfix 0, wenn einstellig. Und ich habe dies verwendet ([1-9] | (1 [0-2])) und es funktioniert.
Bunjeeb
2
Wichtig zu beachten: Wenn Sie auf dieser Seite eine Lösung für Ihren Nummernkreis suchen, die nur einstellige Zahlen enthält, bevor Sie die Zehner erreichen, 0[1-9]|1[0-2]funktioniert dies nicht. Ändere es auf den logischen nächsten Schritt [1-9]|1[0-2]nicht funktioniert entweder aus verständlichen Gründen (es entspricht die 1nur in 10, 11und 12). Musste verwenden \b(?:[0-9]|1[0-1])\b, um das zu verhindern. \b's stellt sicher, dass Regex mit Wort- (oder in diesem Fall Zahlen-) Grenzen übereinstimmt ( ^& $nicht); Klammern lassen das oder ( |) die andere Seite davon betrachten; und schließlich ?:soll kein Submatch mit den Klammern erstellt werden.
user66001
@polygenelubricants: "1,2,3,4,5,6,7,8,9,10,17,18".match(/^(([1-9]|1[0-7])\,?)+$/g )Kannst du mir bitte sagen, warum dieser JS-Regex über 17 übereinstimmt?
Edam
@edam - polygenelubricants konnte, und so konnte ich, aber dann würden wir werden die Beantwortung einer questi ... wait ... ist dies eine Frage Sie in einem fragen Kommentar ? Es gibt Regeln auf dieser Seite;) Stellen Sie eine Frage, wenn Sie eine neue Frage haben. Kommentare dienen nur dazu, zu kritisieren, um Klarstellung zu bitten und auf diese zu antworten.
RobinCTS
1
@edam Oh, ich verstehe. Sie haben es eine Stunde später als Frage erneut gestellt. Das ist großartig! Es wäre jedoch wahrscheinlich eine gute Idee, Ihren Kommentar hier zu löschen.
RobinCTS
24
Eine Zeichenklasse in regulären Ausdrücken, die durch die [...]Syntax gekennzeichnet ist, gibt die Regeln an, die einem einzelnen Zeichen in der Eingabe entsprechen. Daher gibt alles, was Sie in Klammern schreiben, an, wie ein einzelnes Zeichen abgeglichen werden soll .
Ihr Muster [01-12]ist also wie folgt unterteilt:
0 - entspricht der einstelligen 0
oder 1-1 mit einer einzelnen Ziffer im Bereich von 1 bis 1 übereinstimmen
oder 2 mit einer einzelnen Ziffer 2 übereinstimmen
Sie stimmen also im Grunde nur mit 0, 1 oder 2 überein.
Um die gewünschte Übereinstimmung mit zwei Ziffern zwischen 01 und 12 als Zahlen zu erzielen, müssen Sie überlegen, wie sie als Text aussehen.
Du hast:
01-09 (dh die erste Ziffer ist 0, die zweite Ziffer ist 1-9)
10-12 (dh die erste Ziffer ist 1, die zweite Ziffer ist 0-2)
Sie müssen dann einen regulären Ausdruck dafür schreiben, der folgendermaßen aussehen kann:
+-- a 0 followed by1-9||+-- a 1 followed by0-2||<-+--><-+-->0[1-9]|1[0-2]^|+-- vertical bar,this roughly means "OR"inthis context
Beachten Sie, dass der Versuch, sie zu kombinieren, um einen kürzeren Ausdruck zu erhalten, fehlschlägt, indem falsch positive Übereinstimmungen für ungültige Eingaben angegeben werden.
Zum Beispiel [0-1][0-9]würde das Muster im Grunde mit den Zahlen 00-19 übereinstimmen, was etwas mehr ist als Sie wollen.
Ich habe versucht, eine bestimmte Quelle für weitere Informationen zu Zeichenklassen zu finden, aber im Moment kann ich Ihnen nur diese Google-Abfrage für Regex-Zeichenklassen geben . Hoffentlich finden Sie dort weitere Informationen, die Ihnen helfen.
Um genau zu sein, [0-1][0-2]passt auch 00. Das heißt, +1 für den Link (den ich in meiner Antwort verwendet habe).
Polygenelubricants
2
[0-1][0-2]muss sorgfältig interpretiert werden, da es Zeichenfolgen wie 00, 01und erlaubt 02, aber es gibt nicht 03zu 09, endlich zuzugeben 10, 11und 12. Ein richtiger regulärer Ausdruck dafür ist [1-9]|1[0-2]oder sogar 0*([1-9]|1[0-2])(dieser letzte erlaubt eine beliebige Anzahl führender Nullen).
Luis Colorado
1
Das []s in einem regulären Ausdruck bezeichnet eine Zeichenklasse . Wenn keine Bereiche angegeben sind, werden implizit oder alle darin enthaltenen Zeichen zusammen verwendet. Es [abcde]ist also dasselbe wie (a|b|c|d|e), außer dass es nichts erfasst; es wird irgendeine von übereinstimmen a, b, c, d, oder e. Ein Bereich gibt lediglich eine Reihe von Zeichen an . [ac-eg]sagt "stimme mit einem der folgenden aZeichen überein : ; ein beliebiges Zeichen zwischen cund e; oder g". In Ihrem Match heißt es also "Match eines der folgenden 0Zeichen : ; ein beliebiges Zeichen zwischen 1und 1( dh nur 1); oder 2.
Ihr Ziel ist es offensichtlich, einen Nummernkreis anzugeben: eine beliebige Zahl zwischen 01und 12mit zwei Ziffern geschrieben. In diesem speziellen Fall können Sie Folgendes abgleichen 0[1-9]|1[0-2]: entweder eine 0gefolgt von einer beliebigen Ziffer zwischen 1und 9oder eine 1gefolgt von einer beliebigen Ziffer zwischen 0und 2. Im Allgemeinen können Sie einen beliebigen Nummernkreis auf ähnliche Weise in einen gültigen regulären Ausdruck umwandeln. Möglicherweise gibt es jedoch eine bessere Option als reguläre Ausdrücke oder eine vorhandene Funktion oder ein vorhandenes Modul, mit dem der reguläre Ausdruck für Sie erstellt werden kann. Das hängt von Ihrer Sprache ab.
Wie Polygenelubricants sagt, würden Sie eher nach 0 | 1-1 | 2 suchen als nach dem, was Sie sich wünschen, da Zeichenklassen (Dinge in []) eher mit Zeichen als mit Zeichenfolgen übereinstimmen.
[a-z0-9]
Dies entspricht allen Kleinbuchstaben und allen Ziffern, jedoch nur als einzelnes Zeichen.\d+
Muster verwenden, 2.) die übereinstimmenden Zeichenfolgen in Zahlen in Ihrem Code konvertieren. und dann 3.) überprüfen Sie den Nummernkreis wieif(num >= 0 && num <= 12){ /*do something*/ }
. Es ist so viel schneller und flexibler.Antworten:
Sie scheinen falsch verstanden zu haben, wie die Definition von Zeichenklassen in Regex funktioniert.
Um eine der Saiten zu entsprechen
01
,02
,03
,04
,05
,06
,07
,08
,09
,10
,11
, oder12
, so etwas wie dies funktioniert:Verweise
Erläuterung
Eine Zeichenklasse selbst versucht, ein und genau ein Zeichen aus der Eingabezeichenfolge abzugleichen.
[01-12]
tatsächlich definiert[012]
, eine Zeichenklasse , das ein Zeichen aus dem Eingang gegen keines der 3 Zeichen übereinstimmt0
,1
oder2
.Die
-
Bereichsdefinition reicht von1
bis1
, einschließlich just1
. Auf der anderen Seite, so etwas wie[1-9]
beinhaltet1
,2
,3
,4
,5
,6
,7
,8
,9
.Anfänger machen oft die Fehler, Dinge wie zu definieren
[this|that]
. Das "funktioniert" nicht. Dieser Zeichendefinition definiert[this|a]
, dh es ist ein Zeichen aus dem Eingangs gegen keines von 6 Zeichen entspricht int
,h
,i
,s
,|
odera
. Mehr als wahrscheinlich(this|that)
ist das, was beabsichtigt ist.Verweise
Wie Bereiche definiert werden
So ist es jetzt offensichtlich, dass ein Muster wie
between [24-48] hours
"nicht funktioniert". Die Zeichenklasse entspricht in diesem Fall[248]
.Das heißt,
-
in einer Zeichenklasse definiert die Definition keinen numerischen Bereich im Muster. Regex-Engines "verstehen" Zahlen im Muster nicht wirklich, mit Ausnahme der Syntax endlicher Wiederholungen (z. B.a{3,5}
Übereinstimmungen zwischen 3 und 5a
).Die Bereichsdefinition verwendet stattdessen die ASCII / Unicode-Codierung der Zeichen, um Bereiche zu definieren. Das Zeichen
0
wird in ASCII als Dezimalzahl 48 codiert.9
Somit enthält die Zeichendefinition[0-9]
alle Zeichen, deren Werte in der Codierung zwischen 48 und 57 liegen. Vielmehr vernünftig, durch Design , das sind die Zeichen0
,1
, ...,9
.Siehe auch
Ein weiteres Beispiel: A bis Z.
Werfen wir einen Blick auf eine andere allgemeine Definition der Zeichenklasse
[a-zA-Z]
In ASCII:
A
= 65,Z
= 90a
= 97,z
= 122Dies bedeutet, dass:
[a-zA-Z]
und[A-Za-z]
sind gleichwertig[a-Z]
handelt es sich wahrscheinlich um einen illegalen Zeichenbereicha
(97) "größer als" alsZ
(90) ist[A-z]
ist legal, enthält aber auch diese sechs Zeichen:[
(91),\
(92),]
(93),^
(94),_
(95),`
(96)Verwandte Fragen
quelle
0[1-9]|1[0-2]
funktioniert dies nicht. Ändere es auf den logischen nächsten Schritt[1-9]|1[0-2]
nicht funktioniert entweder aus verständlichen Gründen (es entspricht die1
nur in10
,11
und12
). Musste verwenden\b(?:[0-9]|1[0-1])\b
, um das zu verhindern.\b
's stellt sicher, dass Regex mit Wort- (oder in diesem Fall Zahlen-) Grenzen übereinstimmt (^
&$
nicht); Klammern lassen das oder (|
) die andere Seite davon betrachten; und schließlich?:
soll kein Submatch mit den Klammern erstellt werden."1,2,3,4,5,6,7,8,9,10,17,18".match(/^(([1-9]|1[0-7])\,?)+$/g )
Kannst du mir bitte sagen, warum dieser JS-Regex über 17 übereinstimmt?Eine Zeichenklasse in regulären Ausdrücken, die durch die
[...]
Syntax gekennzeichnet ist, gibt die Regeln an, die einem einzelnen Zeichen in der Eingabe entsprechen. Daher gibt alles, was Sie in Klammern schreiben, an, wie ein einzelnes Zeichen abgeglichen werden soll .Ihr Muster
[01-12]
ist also wie folgt unterteilt:Sie stimmen also im Grunde nur mit 0, 1 oder 2 überein.
Um die gewünschte Übereinstimmung mit zwei Ziffern zwischen 01 und 12 als Zahlen zu erzielen, müssen Sie überlegen, wie sie als Text aussehen.
Du hast:
Sie müssen dann einen regulären Ausdruck dafür schreiben, der folgendermaßen aussehen kann:
Beachten Sie, dass der Versuch, sie zu kombinieren, um einen kürzeren Ausdruck zu erhalten, fehlschlägt, indem falsch positive Übereinstimmungen für ungültige Eingaben angegeben werden.
Zum Beispiel
[0-1][0-9]
würde das Muster im Grunde mit den Zahlen 00-19 übereinstimmen, was etwas mehr ist als Sie wollen.Ich habe versucht, eine bestimmte Quelle für weitere Informationen zu Zeichenklassen zu finden, aber im Moment kann ich Ihnen nur diese Google-Abfrage für Regex-Zeichenklassen geben . Hoffentlich finden Sie dort weitere Informationen, die Ihnen helfen.
quelle
Dies funktioniert auch:
^([1-9]|[0-1][0-2])$
[1-9]
stimmt mit einstelligen Zahlen zwischen 1 und 9 überein[0-1][0-2]
entspricht zweistelligen Zahlen zwischen 10 und 12Es gibt einige gute Beispiele hier
quelle
[0-1][0-2]
passt auch00
. Das heißt, +1 für den Link (den ich in meiner Antwort verwendet habe).[0-1][0-2]
muss sorgfältig interpretiert werden, da es Zeichenfolgen wie00
,01
und erlaubt02
, aber es gibt nicht03
zu09
, endlich zuzugeben10
,11
und12
. Ein richtiger regulärer Ausdruck dafür ist[1-9]|1[0-2]
oder sogar0*([1-9]|1[0-2])
(dieser letzte erlaubt eine beliebige Anzahl führender Nullen).Das
[]
s in einem regulären Ausdruck bezeichnet eine Zeichenklasse . Wenn keine Bereiche angegeben sind, werden implizit oder alle darin enthaltenen Zeichen zusammen verwendet. Es[abcde]
ist also dasselbe wie(a|b|c|d|e)
, außer dass es nichts erfasst; es wird irgendeine von übereinstimmena
,b
,c
,d
, odere
. Ein Bereich gibt lediglich eine Reihe von Zeichen an .[ac-eg]
sagt "stimme mit einem der folgendena
Zeichen überein : ; ein beliebiges Zeichen zwischenc
unde
; oderg
". In Ihrem Match heißt es also "Match eines der folgenden0
Zeichen : ; ein beliebiges Zeichen zwischen1
und1
( dh nur1
); oder2
.Ihr Ziel ist es offensichtlich, einen Nummernkreis anzugeben: eine beliebige Zahl zwischen
01
und12
mit zwei Ziffern geschrieben. In diesem speziellen Fall können Sie Folgendes abgleichen0[1-9]|1[0-2]
: entweder eine0
gefolgt von einer beliebigen Ziffer zwischen1
und9
oder eine1
gefolgt von einer beliebigen Ziffer zwischen0
und2
. Im Allgemeinen können Sie einen beliebigen Nummernkreis auf ähnliche Weise in einen gültigen regulären Ausdruck umwandeln. Möglicherweise gibt es jedoch eine bessere Option als reguläre Ausdrücke oder eine vorhandene Funktion oder ein vorhandenes Modul, mit dem der reguläre Ausdruck für Sie erstellt werden kann. Das hängt von Ihrer Sprache ab.quelle
Wie Polygenelubricants sagt, würden Sie eher nach 0 | 1-1 | 2 suchen als nach dem, was Sie sich wünschen, da Zeichenklassen (Dinge in []) eher mit Zeichen als mit Zeichenfolgen übereinstimmen.
quelle
0|1-1|2
- Diese Notation ist sehr irreführend. So etwas0|1|2
wäre genauer.Benutze das:
Verwenden Sie Folgendes, um ein Muster als 07/2018 zu testen:
(Datumsbereich zwischen 01/2000 bis 12/9999)
quelle