巴西税号CNPJ的全称是Cadastro Nacional da Pessoa Jurídica,是巴西联邦税务局分配给企业的唯一识别编号,标准格式为XX.XXX.XXX/XXXX-XX,共14位数字,包含分隔符的情况下总长度为18位。在数据处理过程中,我们经常需要从文本、表单输入或者数据库字段中提取符合规则的CNPJ信息,这时候就需要使用正则表达式来完成匹配。

CNPJ的格式规则说明
CNPJ的基础结构分为四个部分,具体规则如下:
- 前8位为基础编号,为企业的核心识别码
- 第9到12位为分支编号,用于区分同一企业的不同分支机构
- 第13到14位为校验位,通过特定算法计算得出,用于验证CNPJ的合法性
- 标准展示格式会在对应位置添加点、斜杠、横杠分隔符,分别为XX.XXX.XXX/XXXX-XX
实际业务中,CNPJ可能出现带分隔符、不带分隔符、分隔符缺失或错误等多种情况,因此通用匹配方案需要兼容这些场景。
通用正则表达式设计
我们需要设计的通用正则需要满足以下匹配场景:
- 完整带标准分隔符的CNPJ:XX.XXX.XXX/XXXX-XX
- 不带任何分隔符的14位纯数字CNPJ
- 分隔符存在但不完整的CNPJ,比如缺少部分点或者斜杠的情况
最终的通用正则表达式如下:
d{2}.?d{3}.?d{3}/?d{4}-?d{2}|d{14}
这个正则的含义拆解:
d{2}.?d{3}.?d{3}/?d{4}-?d{2}匹配带可选分隔符的CNPJ,其中.?表示点号可选,/?表示斜杠可选,-?表示横杠可选|是正则的或运算符,连接两种匹配规则d{14}匹配14位纯数字的CNPJ
不同场景下的使用示例
Python中提取CNPJ
使用re模块实现从文本中提取所有符合规则的CNPJ:
import re
# 通用CNPJ正则
cnpj_pattern = r'd{2}.?d{3}.?d{3}/?d{4}-?d{2}|d{14}'
# 测试文本,包含多种格式的CNPJ
test_text = "企业A的CNPJ是12.345.678/0001-90,企业B的CNPJ是12345678000190,企业C的CNPJ是12.345.678/0001-90"
# 提取所有匹配的CNPJ
cnpj_list = re.findall(cnpj_pattern, test_text)
print("提取到的CNPJ列表:")
for cnpj in cnpj_list:
print(cnpj)
JavaScript中校验CNPJ格式
在前端表单校验场景中使用该正则判断用户输入的CNPJ是否合法:
// 通用CNPJ正则
const cnpjPattern = /d{2}.?d{3}.?d{3}/?d{4}-?d{2}|d{14}/;
// 测试不同的CNPJ输入
const testCnpjs = ["12.345.678/0001-90", "12345678000190", "12.345.678/000190", "1234567890"];
testCnpjs.forEach(cnpj => {
if (cnpjPattern.test(cnpj)) {
console.log(`${cnpj} 是合法的CNPJ格式`);
} else {
console.log(`${cnpj} 不是合法的CNPJ格式`);
}
});
Java中处理CNPJ提取
使用Java的正则表达式类完成CNPJ的提取操作:
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.ArrayList;
import java.util.List;
public class CnpjExtractor {
public static void main(String[] args) {
// 通用CNPJ正则
String cnpjRegex = "\d{2}\.?\d{3}\.?\d{3}\/?\d{4}\-?\d{2}|\d{14}";
Pattern pattern = Pattern.compile(cnpjRegex);
// 测试文本
String testText = "合作方信息:CNPJ 12.345.678/0001-90,备用编号12345678000190";
Matcher matcher = pattern.matcher(testText);
List<String> cnpjList = new ArrayList<>();
while (matcher.find()) {
cnpjList.add(matcher.group());
}
System.out.println("提取到的CNPJ:");
for (String cnpj : cnpjList) {
System.out.println(cnpj);
}
}
}
正则的优化建议
如果需要严格校验CNPJ的合法性,仅用上述正则是不够的,还需要额外添加校验位校验逻辑,因为上述正则会匹配所有符合格式的数字组合,包含校验位错误的无效CNPJ。如果只需要提取符合格式的文本不需要校验合法性,上述通用正则已经可以满足大部分场景需求。
另外在批量处理大量文本时,可以先对文本做预处理,去除无关的特殊字符,再使用正则匹配,可以提升匹配效率,减少误匹配的概率。