Expresiones Regulares para validar RUC (o CI) de Paraguay

25 de Junio de 2023

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”.

La expresión regular (regex) rebuscada:

^(?:(?!0)\d{6,8}|(?!0)\d{5,7}A)(?:-\d)?$

La explicación, parte por parte

  • ^: 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

La expresión regular (regex) más corta y concisa:

^[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.

La explicación, fragmento a fragmento

  • ^: 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 cadena

Cadenas de prueba

012345            # 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

Para tener en cuenta

  • Se asume que el único caracter alfanumérico presente (de estarlo) será la “A” mayúscula en el primer ejemplo, y en el segundo, o la A, B, C o D.
  • Las expresiones regulares no validan si el documento ingresado es de una persona física o jurídica.
  • Se asume que la longitud del documento (sin el guión + dígito verificador) es de 6 a 8 caracteres. \

Bonus


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)?$

Recordatorio adicional


Regex no es la panacea para validar cadenas. Ya decían por ahí algo así como lo siguiente:

"Algunos, cuando se enfrentan a un problema, piensan “ya sé, usaré expresiones regulares”. Ahora tienen dos problemas."




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 (?


Hugo Theme: "Bulma Hugo Resume", basado en  Hugo Resume