Regular expression to validate a field that accepts CPF or CNPJ (without calculating the digits checkers):
/^([0-9]{3}\.?[0-9]{3}\.?[0-9]{3}\-?[0-9]{2}|[0-9]{2}\.?[0-9]{3}\.?[0-9]{3}\/?[0-9]{4}\-?[0-9]{2})$/
It can be understood like this (where "cpf" is the expression to validate CPF and "cnpj" is the expression to validate CNPJ):
/^(cpf|cnpj)$/
The start and end bars ( /
) are not part of the expression itself - they are only delimiters. The ^
character at the beginning and the $
character at the end require that the complete contents of string
to be valid match the expression between them. Parentheses containing the (a|b)
vertical bar create an alternative "option" between " a
" and " b
". Satisfying either expression, the result will be positive. Instead of " a
" and " b
", we then have the specific expressions for CPF and CNPJ, separately.
For CPF:
[0-9]{3}\.?[0-9]{3}\.?[0-9]{3}\-?[0-9]{2}
The interrogation ( ?
) causes the preceding character specification to be optional . Therefore the points and the tracino are optional. The character type [0-9]
represents any character from 0
to 9
(we could use \d
, but I prefer [0-9]
because it is more readable). Finally, the number in brackets (% w / o%) determines a specific number of times that the preceding character specification must be repeated. Thus, a total of 11 numeric characters (3 + 3 + 3 + 2) are required.
For CNPJ, the structure is similar:
[0-9]{2}\.?[0-9]{3}\.?[0-9]{3}\/?[0-9]{4}\-?[0-9]{2}
A total of 14 numeric characters (2 + 3 + 3 + 4 + 2) are required here.
Remembering that the backslash ( {3}
) before the point ( \
) and other special characters is an "escape" character, which serves to disregard the special interpretation of the next character and to consider it literally. (The dot, without "escape," means "any character." With "escape," it merely means the "dot" character itself.)
To find out if you are a CPF or CNPJ
On the server side, in PHP, the selection is made between CPF or CNPJ considering the number of digits present in the field:
$numeros = preg_replace('/[^0-9]/', '', $valor);
if (strlen($numeros) == 11)
{
$cliente->cpf = $valor;
}
elseif (strlen($numbers) == 14)
{
$cliente->cnpj = $valor;
}
Note : this does not replace the validation made by the regular expression we saw above, which is also performed on the server side (in my case the rules are embedded in the template with the same regular expressions of validation that we have seen above for CPF and CNPJ, only separate - each in its respective field).