Regex como combinar um caractere opcional

147

Eu tenho uma regex que pensei que estava funcionando corretamente até agora. Preciso combinar com um caractere opcional. Pode estar lá ou não.

Aqui estão duas strings. A corda superior é correspondida enquanto a inferior não. A ausência de uma única letra na cadeia inferior é o que está fazendo com que ela falhe.

Gostaria de obter a letra única após os 5 dígitos iniciais, se ela estiver lá e, se não estiver, continue obtendo o restante da string. Esta carta pode ser A-Z.

Se eu remover ([A-Z]{1}) +.*? +do regex, ele corresponderá a tudo o que preciso, exceto a letra, mas é meio importante.

20000      K               Q511195DREWBT            E00078748521
30000                      K601220PLOPOH            Z00054878524

Aqui está o regex que estou usando.

/^([0-9]{5})+.*? ([A-Z]{1}) +.*? +([A-Z]{1})([0-9]{3})([0-9]{3})([A-Z]{3})([A-Z]{3}) +([A-Z])[0-9]{3}([0-9]{4})([0-9]{2})([0-9]{2})/
jim
fonte

Respostas:

246

Usar

[A-Z]?

para tornar a letra opcional. {1}é redundante. (É claro que você também pode escrever o [A-Z]{0,1}que significaria o mesmo, mas é para isso que ?existe.)

Você pode melhorar seu regex para

^([0-9]{5})+\s+([A-Z]?)\s+([A-Z])([0-9]{3})([0-9]{3})([A-Z]{3})([A-Z]{3})\s+([A-Z])[0-9]{3}([0-9]{4})([0-9]{2})([0-9]{2})

E, como na maioria dos dialetos regex, \dé o mesmo que [0-9]:

^(\d{5})+\s+([A-Z]?)\s+([A-Z])(\d{3})(\d{3})([A-Z]{3})([A-Z]{3})\s+([A-Z])\d{3}(\d{4})(\d{2})(\d{2})

Mas: você realmente precisa de 11 grupos de captura separados? E se sim, por que você não captura o penúltimo grupo de dígitos?

Tim Pietzcker
fonte
Tim, sinceramente não tenho certeza, pois não escrevi esse regex. Eu ainda sou muito novo em regex. Se você vir uma maneira melhor de escrever isso, estou aberto a sugestões.
jim
1
Tim, seu exemplo funciona para as duas cadeias, tenha ou não uma carta nessa posição. Obrigado.
jim
26

Você pode tornar a letra única opcional, adicionando um ?depois como:

([A-Z]{1}?)

O quantificador {1}é redundante para que você possa descartá-lo.

codaddict
fonte
Obrigado codeaddict. O ponto de interrogação substitui o `+. *? + `?
jim
Ao usar o grep regex, você receberá um erro se você soltar o {1} (grep: assertion lookbehind não tem tamanho fixo). Então esse é um caso para deixá-lo em.
Zunderscore
6

Você também deve marcar a letra como opcional:

([A-Z]{1})? +.*? +

ou faça a parte inteira opcional

(([A-Z]{1}) +.*? +)?
Stefan
fonte
1
Stefan, gostaria de tornar a carta totalmente opcional. Eu tentei os dois, mas ainda não corresponde a nada. Tenho certeza de que entendi errado. Você poderia modificar seu exemplo para incluí-lo na cadeia?
jim
0

Você também pode usar regex mais simples, projetado para o seu caso, como (.*)\/(([^\?\n\r])*)onde $2corresponde ao que você deseja.

robinvrd
fonte