Você está combinando personagens , não sequências de caracteres . Basicamente, você está combinando com 0, 1 a 1 e 2 (ou seja, 0, 1 e 2). Considere [a-z0-9]o seguinte:, corresponde a todas as letras minúsculas e a todos os dígitos, mas apenas como um único caractere.
0 [1-9] | 1 [0-2] -> 0 | 1 | 2 -> [] s em uma regex denotam uma classe de caracteres. Se nenhum intervalo for especificado, ele implicitamente ors cada caractere.
Badri Gs
Você precisa combiná-lo com regex puro? Se não, você pode: 1.) simplesmente usar o \d+padrão, 2.) converter as strings correspondentes em números em seu código. e então, 3.) verifique o intervalo de números como if(num >= 0 && num <= 12){ /*do something*/ }. É muito mais rápido e flexível.
acegs
Respostas:
192
Você parece não ter entendido como a definição das classes de caracteres funciona no regex.
Para combinar com qualquer das cordas 01, 02, 03, 04, 05, 06, 07, 08, 09, 10,11 , ou 12, algo como isso funciona:
Intervalos numéricos (tem muitos exemplos de strings correspondentes interpretadas como intervalos numéricos)
Explicação
Uma classe de caractere, por si só, tenta corresponder a um e exatamente um caractere da string de entrada. [01-12]realmente define [012], uma classe de caracteres que corresponde a um carácter de entrada contra qualquer um dos 3 caracteres 0, 1ou2 .
A -definição de intervalo vai de 1a 1, que inclui apenas 1. Por outro lado, algo como [1-9]inclui 1, 2, 3, 4, 5, 6, 7, 8,9 .
Iniciantes costumam cometer erros de definição de coisas como [this|that]. Isso não "funciona". Este personagem define definição [this|a], isto é, ele corresponde a um carácter de entrada contra qualquer de 6 caracteres de t, h, i, s, |ou a. Mais do que provável(this|that) é o que se pretende.
Portanto, é óbvio agora que um padrão como between [24-48] hoursnão "funciona". A classe de caracteres, neste caso, é equivalente a[248] .
Ou seja, -em uma definição de classe de caractere não define intervalo numérico no padrão. Os motores Regex não "entendem" realmente os números no padrão, com exceção da sintaxe de repetição finita (por exemplo, a{3,5}correspondências entre 3 e 5 a).
Em vez disso, a definição de intervalo usa a codificação ASCII / Unicode dos caracteres para definir intervalos. O caractere 0é codificado em ASCII como decimal 48; 9é 57. Assim, a definição de caractere [0-9]inclui todos os caracteres cujos valores estão entre o decimal 48 e 57 na codificação. Em vez de forma sensata, pelo projeto Estes são os personagens 0, 1, ..., 9.
Para mim, estava procurando meses sem prefixar 0 se fosse um dígito. E eu usei isso ([1-9] | (1 [0-2])) e funciona.
Bunjeeb
2
Importante observar: se você achar que esta página deseja uma solução para seu intervalo numérico que tenha apenas um dígito antes de chegar às dezenas, 0[1-9]|1[0-2]não funcionará. Alterá-lo para a próxima etapa lógica [1-9]|1[0-2]não quer trabalhar por razões compreensíveis (Ele corresponde a 1apenas em 10, 11, e 12). Tive que usar \b(?:[0-9]|1[0-1])\bpara evitar isso. \bfaz com que o regex corresponda aos limites da palavra (ou, neste caso, número) ( ^& $não); os colchetes fazem o ou ( |) considerar o outro lado dele; e, por fim, ?:não é criar uma submatch com o uso dos colchetes.
user66001
@polygenelubricants: "1,2,3,4,5,6,7,8,9,10,17,18".match(/^(([1-9]|1[0-7])\,?)+$/g )Você pode me dizer por que essa regex JS corresponde a mais de 17?
edam
@edam - poligenelubrificantes poderiam, e eu também, mas então estaríamos respondendo um questi ... espera ... esta é uma pergunta que você está pedindo em um comentário ? Existem rulez neste site;) Faça uma pergunta se tiver uma nova pergunta. Os comentários são apenas para criticar e pedir esclarecimentos e para responder a eles.
robinCTS
1
@edam Oh, entendo. Você fez uma pergunta novamente uma hora depois. Isso é ótimo! No entanto, provavelmente seria uma boa ideia excluir seu comentário aqui.
robinCTS
24
Uma classe de caractere em expressões regulares, denotada pela [...]sintaxe, especifica as regras para corresponder a um único caractere na entrada. Como tal, tudo o que você escreve entre os colchetes especifica como combinar um único caractere .
Seu padrão [01-12]é , portanto, dividido da seguinte forma:
0 - corresponde ao único dígito 0
ou, 1-1, corresponde a um único dígito no intervalo de 1 a 1
ou, 2, corresponde a um único dígito 2
Basicamente, você só está correspondendo a 0, 1 ou 2.
Para fazer a correspondência desejada, combinando dois dígitos, variando de 01 a 12 como números, você precisa pensar em como eles ficarão como texto.
Você tem:
01-09 (ou seja, o primeiro dígito é 0, o segundo dígito é 1-9)
10-12 (ou seja, o primeiro dígito é 1, o segundo dígito é 0-2)
Você terá que escrever uma expressão regular para isso, que pode ser parecida com esta:
+-- a 0 followed by1-9||+-- a 1 followed by0-2||<-+--><-+-->0[1-9]|1[0-2]^|+-- vertical bar,this roughly means "OR"inthis context
Observe que tentar combiná-los para obter uma expressão mais curta falhará, fornecendo correspondências positivas falsas para entrada inválida.
Por exemplo, o padrão [0-1][0-9]corresponderia basicamente aos números 00-19, o que é um pouco mais do que você deseja.
Tentei encontrar uma fonte definitiva para obter mais informações sobre classes de personagens, mas por enquanto tudo que posso dar é esta Google Query para Regex Character Classes . Esperançosamente, você encontrará mais informações para ajudá-lo.
Para ser exato, [0-1][0-2]também corresponde 00. Dito isso, +1 para o link (que usei na minha resposta).
poligenelubrificantes
2
[0-1][0-2]devem ser interpretados com cautela, uma vez que permite cordas gosto 00, 01e 02, mas não admite 03até 09, admitindo finalmente 10, 11e 12. Um regex correto para isso é [1-9]|1[0-2], ou mesmo 0*([1-9]|1[0-2])(este último permitindo qualquer número de zeros à esquerda).
Luis Colorado
1
Os []s em uma regex denotam uma classe de caracteres . Se nenhum intervalo for especificado, ele implicitamente ou todos os caracteres dentro dele juntos. Portanto, [abcde]é o mesmo que (a|b|c|d|e), exceto que não captura nada; ele irá corresponder a qualquer um dos a, b, c, d, ou e. Tudo o que um intervalo indica é um conjunto de caracteres ; [ac-eg]diz "corresponde a qualquer um de a:; qualquer caractere entre ce e; ou g". Assim, sua correspondência diz "corresponder a qualquer um de 0:; qualquer caractere entre 1e 1( ou seja , apenas 1); ou2 .
Seu objetivo é evidentemente especificar um intervalo de números: qualquer número entre 01e 12escrito com dois dígitos. Neste caso específico, você pode combiná-lo com 0[1-9]|1[0-2]: a 0seguido por qualquer dígito entre 1e 9, ou a 1seguido por qualquer dígito entre 0e 2. Em geral, você pode transformar qualquer intervalo de números em uma regex válida de maneira semelhante. Pode haver uma opção melhor do que expressões regulares, no entanto, ou uma função ou módulo existente que pode construir a regex para você. Depende do seu idioma.
Como os poligenelubrificantes dizem, o seu procuraria 0 | 1-1 | 2 em vez do que você deseja, devido ao fato de que as classes de caracteres (coisas em []) correspondem a caracteres em vez de strings.
[a-z0-9]
o seguinte:, corresponde a todas as letras minúsculas e a todos os dígitos, mas apenas como um único caractere.\d+
padrão, 2.) converter as strings correspondentes em números em seu código. e então, 3.) verifique o intervalo de números comoif(num >= 0 && num <= 12){ /*do something*/ }
. É muito mais rápido e flexível.Respostas:
Você parece não ter entendido como a definição das classes de caracteres funciona no regex.
Para combinar com qualquer das cordas
01
,02
,03
,04
,05
,06
,07
,08
,09
,10
,11
, ou12
, algo como isso funciona:Referências
Explicação
Uma classe de caractere, por si só, tenta corresponder a um e exatamente um caractere da string de entrada.
[01-12]
realmente define[012]
, uma classe de caracteres que corresponde a um carácter de entrada contra qualquer um dos 3 caracteres0
,1
ou2
.A
-
definição de intervalo vai de1
a1
, que inclui apenas1
. Por outro lado, algo como[1-9]
inclui1
,2
,3
,4
,5
,6
,7
,8
,9
.Iniciantes costumam cometer erros de definição de coisas como
[this|that]
. Isso não "funciona". Este personagem define definição[this|a]
, isto é, ele corresponde a um carácter de entrada contra qualquer de 6 caracteres det
,h
,i
,s
,|
oua
. Mais do que provável(this|that)
é o que se pretende.Referências
Como os intervalos são definidos
Portanto, é óbvio agora que um padrão como
between [24-48] hours
não "funciona". A classe de caracteres, neste caso, é equivalente a[248]
.Ou seja,
-
em uma definição de classe de caractere não define intervalo numérico no padrão. Os motores Regex não "entendem" realmente os números no padrão, com exceção da sintaxe de repetição finita (por exemplo,a{3,5}
correspondências entre 3 e 5a
).Em vez disso, a definição de intervalo usa a codificação ASCII / Unicode dos caracteres para definir intervalos. O caractere
0
é codificado em ASCII como decimal 48;9
é 57. Assim, a definição de caractere[0-9]
inclui todos os caracteres cujos valores estão entre o decimal 48 e 57 na codificação. Em vez de forma sensata, pelo projeto Estes são os personagens0
,1
, ...,9
.Veja também
Outro exemplo: A a Z
Vamos dar uma olhada em outra definição de classe de personagem comum
[a-zA-Z]
Em ASCII:
A
= 65,Z
= 90a
= 97,z
= 122Isso significa que:
[a-zA-Z]
e[A-Za-z]
são equivalentes[a-Z]
é provável que seja um intervalo de caracteres ilegala
(97) é "maior que" queZ
(90)[A-z]
é legal, mas também inclui estes seis caracteres:[
(91),\
(92),]
(93),^
(94),_
(95),`
(96)Perguntas relacionadas
fonte
0[1-9]|1[0-2]
não funcionará. Alterá-lo para a próxima etapa lógica[1-9]|1[0-2]
não quer trabalhar por razões compreensíveis (Ele corresponde a1
apenas em10
,11
, e12
). Tive que usar\b(?:[0-9]|1[0-1])\b
para evitar isso.\b
faz com que o regex corresponda aos limites da palavra (ou, neste caso, número) (^
&$
não); os colchetes fazem o ou (|
) considerar o outro lado dele; e, por fim,?:
não é criar uma submatch com o uso dos colchetes."1,2,3,4,5,6,7,8,9,10,17,18".match(/^(([1-9]|1[0-7])\,?)+$/g )
Você pode me dizer por que essa regex JS corresponde a mais de 17?Uma classe de caractere em expressões regulares, denotada pela
[...]
sintaxe, especifica as regras para corresponder a um único caractere na entrada. Como tal, tudo o que você escreve entre os colchetes especifica como combinar um único caractere .Seu padrão
[01-12]
é , portanto, dividido da seguinte forma:Basicamente, você só está correspondendo a 0, 1 ou 2.
Para fazer a correspondência desejada, combinando dois dígitos, variando de 01 a 12 como números, você precisa pensar em como eles ficarão como texto.
Você tem:
Você terá que escrever uma expressão regular para isso, que pode ser parecida com esta:
Observe que tentar combiná-los para obter uma expressão mais curta falhará, fornecendo correspondências positivas falsas para entrada inválida.
Por exemplo, o padrão
[0-1][0-9]
corresponderia basicamente aos números 00-19, o que é um pouco mais do que você deseja.Tentei encontrar uma fonte definitiva para obter mais informações sobre classes de personagens, mas por enquanto tudo que posso dar é esta Google Query para Regex Character Classes . Esperançosamente, você encontrará mais informações para ajudá-lo.
fonte
Isso também funciona:
^([1-9]|[0-1][0-2])$
[1-9]
corresponde a dígitos únicos entre 1 e 9[0-1][0-2]
corresponde a dois dígitos entre 10 e 12Existem alguns bons exemplos aqui
fonte
[0-1][0-2]
também corresponde00
. Dito isso, +1 para o link (que usei na minha resposta).[0-1][0-2]
devem ser interpretados com cautela, uma vez que permite cordas gosto00
,01
e02
, mas não admite03
até09
, admitindo finalmente10
,11
e12
. Um regex correto para isso é[1-9]|1[0-2]
, ou mesmo0*([1-9]|1[0-2])
(este último permitindo qualquer número de zeros à esquerda).Os
[]
s em uma regex denotam uma classe de caracteres . Se nenhum intervalo for especificado, ele implicitamente ou todos os caracteres dentro dele juntos. Portanto,[abcde]
é o mesmo que(a|b|c|d|e)
, exceto que não captura nada; ele irá corresponder a qualquer um dosa
,b
,c
,d
, oue
. Tudo o que um intervalo indica é um conjunto de caracteres ;[ac-eg]
diz "corresponde a qualquer um dea
:; qualquer caractere entrec
ee
; oug
". Assim, sua correspondência diz "corresponder a qualquer um de0
:; qualquer caractere entre1
e1
( ou seja , apenas1
); ou2
.Seu objetivo é evidentemente especificar um intervalo de números: qualquer número entre
01
e12
escrito com dois dígitos. Neste caso específico, você pode combiná-lo com0[1-9]|1[0-2]
: a0
seguido por qualquer dígito entre1
e9
, ou a1
seguido por qualquer dígito entre0
e2
. Em geral, você pode transformar qualquer intervalo de números em uma regex válida de maneira semelhante. Pode haver uma opção melhor do que expressões regulares, no entanto, ou uma função ou módulo existente que pode construir a regex para você. Depende do seu idioma.fonte
Como os poligenelubrificantes dizem, o seu procuraria 0 | 1-1 | 2 em vez do que você deseja, devido ao fato de que as classes de caracteres (coisas em []) correspondem a caracteres em vez de strings.
fonte
0|1-1|2
- esta notação é muito enganosa. Algo como0|1|2
seria mais preciso.Usa isto:
Para testar um padrão como 07/2018, use o seguinte:
(Intervalo de datas entre 01/2000 a 12/9999)
fonte