Teniendo tantas cosas importantes por hacer en un domingo, no tuve mejor idea que procrastinar con expresiones regulares 😀
Aclaración preliminar: queda a criterio del lector investigar qué son los “grupos sin captura” y las “búsquedas anticipadas negativas”.
^(?:(?!0)\d{6,8}|(?!0)\d{5,7}A)(?:-\d)?$
^
: Inicio de la cadena(?:(?!0)\d{6,8}|(?!0)\d{5,7}A)
:(?:)
: Grupo sin captura (non-captouring group): no “memoriza” el texto coincidente; agrupa tokens sin convertirse en un grupo de captura(?!)
: Búsqueda anticipada negativa (negative lookahead): El grupo no debe coincidir con la expresión dada(?!0)
: Evitar que la cadena empiece con “0”\d{6,8}
: Dígitos del 0 al 9 (\d
es el equivalente de [0-9]
), de 6 a 8 veces\|
: “o” (tal como el operador “or”)\d{5,7}A
: Dígitos del 0 al 9 (\d
es el equivalente de [0-9]
), de 5 a 7 veces, seguido de una “A” (para contemplar documentos con caracteres alfanuméricos)(?:)
: Grupo sin captura (non-captouring group): no “memoriza” el texto coincidente; agrupa tokens sin convertirse en un grupo de captura-\d
: Un guión, seguido de dígitos del 0 al 9 (\d
es el equivalente de [0-9]
)?
: Opcional: Puede o no aparecer$
: Fin de la cadena^[1-9]\d{4,6}[\dA-D](?:-\d)?$
Esta versión se me ocurrió en base al regex de este xsd del SIFEN, específicamente del xs:simpleType
tRuc.
^
: Inicio de la cadena[1-9]
: Un dígito del 1 al 9 (para evitar que la cadena empiece con “0”)\d{4,6}
: Dígitos del 0 al 9 (\d
es el equivalente de [0-9]
), de 6 a 8 veces[\dA-D]
: Un dígito del 0 al 9 (\d
es el equivalente de [0-9]
), o la letra A/B/C/D mayúscula(?:)
: Grupo sin captura (non-captouring group): no “memoriza” el texto coincidente; agrupa tokens sin convertirse en un grupo de captura-\d
: Un guión, seguido de dígitos del 0 al 9 (\d
es el equivalente de [0-9]
)?
: Opcional: Puede o no aparecer$
: Fin de la cadena012345 # no coincide
0123456 # no coincide
01234567 # no coincide
012345678 # no coincide
12345 # no coincide
123456 # coincide
1234657 # coincide
12345678 # coincide
123456789 # no coincide
01234A # no coincide
012345A # no coincide
0123456A # no coincide
01234567A # no coincide
012345678A # no coincide
12345A # coincide
123456A # coincide
1234567A # coincide
12345678A # no coincide
123456789A # no coincide
12345- # no coincide
123456- # no coincide
12345678- # no coincide
123456789- # no coincide
12345A- # no coincide
123456A- # no coincide
1234567A- # no coincide
12345678A- # no coincide
123456789A- # no coincide
123456-0 # coincide
1234567-0 # coincide
12345678-0 # coincide
123456789-0 # no coincide
12345A-0 # coincide
123456A-0 # coincide
1234567A-0 # coincide
12345678A-0 # no coincide
123456789A-0 # no coincide
Si por algún motivo sí se necesita trabajar con los grupos de captura (ej.: para calcular el dígito verificador del documento sin guión), las versiones con grupos de captura serían las siguientes:
^((?!0)\d{6,8}|(?!0)\d{5,7}A)(-\d)?$
^[1-9]\d{4,6}[\dA-D](-\d)?$
Regex no es la panacea para validar cadenas. Ya decían por ahí algo así como lo siguiente:
No está demás mencionar que pueden contactarme si tienen sugerencias de corrección para los regex. En la sección inicial del sitio se encuentran los enlaces de contacto 👌
Fueron testeados en Javascript. Si funcionan para otros lenguajes, me avisan también 🙏
Por último, dejé esta respuesta en StackOverflow ya que la respuesta aceptada no me convencía del todo (?