从字符串中提取符合规则的汽车车牌

复制代码
import com.alibaba.fastjson2.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Slf4j
@Component
public class LicensePlateExtractorUtil {
    // 蓝牌正则:省份简称(1汉字) + 发牌机关代号(1字母) + 5位序号(字母/数字)
    // 排除I和O避免与1和0混淆
    private static final String BLUE_PLATE_REGEX = "[\\u4e00-\\u9fa5][A-Z][A-HJ-NP-Z0-9]{5}";

    // 新能源车牌正则:
    // 小型车:省份简称(1汉字) + 发牌机关代号(1字母,D/F) + 6位序号(前4位数字+后1位字母)
    // 大型车:省份简称(1汉字) + 发牌机关代号(1字母) + 6位序号(前1位字母+后5位数字)
    private static final String NEW_ENERGY_PLATE_REGEX = "[\\u4e00-\\u9fa5][A-Z][A-HJ-NP-Z0-9]{6}";

    // 使馆车牌正则 (特殊车牌示例)
    private static final String EMBASSY_PATTERN = "使[A-Z0-9]{6}";

    // 武警车牌正则 (特殊车牌示例)
    private static final String MILITARY_PATTERN = "WJ[\\u4e00-\\u9fa5]{0,1}[0-9]{5}";

    // 合并正则
    private static final String COMBINED_REGEX =  NEW_ENERGY_PLATE_REGEX + "|" + BLUE_PLATE_REGEX + "|" + EMBASSY_PATTERN + "|" + MILITARY_PATTERN;

    // 预编译正则
    private static final Pattern PLATE_PATTERN = Pattern.compile(COMBINED_REGEX);

    // 中国省级行政区简称集合(包括省、自治区、直辖市、特别行政区)
    private static final Set<String> VALID_PROVINCE_CODES;

    static {
        // 初始化有效省份简称集合
        VALID_PROVINCE_CODES = new HashSet<>();
        // 直辖市
        VALID_PROVINCE_CODES.add("京"); // 北京
        VALID_PROVINCE_CODES.add("津"); // 天津
        VALID_PROVINCE_CODES.add("沪"); // 上海
        VALID_PROVINCE_CODES.add("渝"); // 重庆
        // 省
        VALID_PROVINCE_CODES.add("冀"); // 河北
        VALID_PROVINCE_CODES.add("晋"); // 山西
        VALID_PROVINCE_CODES.add("辽"); // 辽宁
        VALID_PROVINCE_CODES.add("吉"); // 吉林
        VALID_PROVINCE_CODES.add("黑"); // 黑龙江
        VALID_PROVINCE_CODES.add("苏"); // 江苏
        VALID_PROVINCE_CODES.add("浙"); // 浙江
        VALID_PROVINCE_CODES.add("皖"); // 安徽
        VALID_PROVINCE_CODES.add("闽"); // 福建
        VALID_PROVINCE_CODES.add("赣"); // 江西
        VALID_PROVINCE_CODES.add("鲁"); // 山东
        VALID_PROVINCE_CODES.add("豫"); // 河南
        VALID_PROVINCE_CODES.add("鄂"); // 湖北
        VALID_PROVINCE_CODES.add("湘"); // 湖南
        VALID_PROVINCE_CODES.add("粤"); // 广东
        VALID_PROVINCE_CODES.add("琼"); // 海南
        VALID_PROVINCE_CODES.add("川"); // 四川
        VALID_PROVINCE_CODES.add("贵"); // 贵州
        VALID_PROVINCE_CODES.add("云"); // 云南
        VALID_PROVINCE_CODES.add("陕"); // 陕西
        VALID_PROVINCE_CODES.add("甘"); // 甘肃
        VALID_PROVINCE_CODES.add("青"); // 青海
        VALID_PROVINCE_CODES.add("台"); // 台湾
        // 自治区
        VALID_PROVINCE_CODES.add("蒙"); // 内蒙古
        VALID_PROVINCE_CODES.add("桂"); // 广西
        VALID_PROVINCE_CODES.add("宁"); // 宁夏
        VALID_PROVINCE_CODES.add("新"); // 新疆
        VALID_PROVINCE_CODES.add("藏"); // 西藏
        // 特别行政区
        VALID_PROVINCE_CODES.add("港"); // 香港
        VALID_PROVINCE_CODES.add("澳"); // 澳门
    }

    /**
     * 从字符串中提取所有蓝牌和新能源车牌
     * @param input 待提取的字符串
     * @return 提取到的车牌列表,无匹配时返回空列表
     */
    public static List<String> extractAllPlates(String input) {
        List<String> plates = new ArrayList<>();
        if (input == null || input.isEmpty()) {
            return plates;
        }

        Matcher matcher = PLATE_PATTERN.matcher(input);
        while (matcher.find()) {
            String group = matcher.group();

            String provinceCode = group.substring(0, 1);
            if (StringUtils.equals(provinceCode,"使") || StringUtils.equals(provinceCode,"W")){

            }else {
                boolean validProvinceCode = isValidProvinceCode(provinceCode);
                if (!validProvinceCode){
                    continue;
                }
            }

            plates.add(group);
        }
        return plates;
    }

    /**
     * 区分蓝牌和新能源车牌
     * @param plate 车牌号码
     * @return 车牌类型描述
     */
    public static String getPlateType(String plate) {
        if (plate == null) {
            return "无效车牌";
        }
        if (plate.matches(BLUE_PLATE_REGEX)) {
            return "蓝牌";
        } else if (plate.matches(NEW_ENERGY_PLATE_REGEX)) {
            return "新能源车牌";
        }  else if (plate.matches(EMBASSY_PATTERN)) {
            return "使馆车牌";
        }  else if (plate.matches(MILITARY_PATTERN)) {
            return "武警车牌";
        } else {
            return "无效车牌";
        }
    }

    /**
     * 校验省份简称是否有效
     * @param code 省份简称(单个汉字)
     * @return true-有效,false-无效
     */
    public static boolean isValidProvinceCode(String code) {
        // 校验输入是否为单个汉字
        if (code == null || code.length() != 1) {
            return false;
        }
        // 校验是否在有效集合中
        return VALID_PROVINCE_CODES.contains(code);
    }

    public static void main(String[] args) {
        String testStr = "停车场内有:京A12345(蓝牌)、粤AD12345(新能源)、沪B67890(蓝牌)、苏AF67890(新能源)、无效车牌ABC123、使123456、WJ123456、冀X12345";

        // 提取车牌
        List<String> plates = extractAllPlates(testStr);
        System.out.println("提取到的车牌:" + JSONObject.toJSONString(plates));
        for (String plate : plates) {
            System.out.println(plate + "|" + getPlateType(plate));
        }
    }
}

代码执行结果:

提取到的车牌:["京A12345","粤AD12345","沪B67890","苏AF67890","使123456","WJ12345","冀X12345"]

京A12345|蓝牌

粤AD12345|新能源车牌

沪B67890|蓝牌

苏AF67890|新能源车牌

使123456|使馆车牌

WJ12345|武警车牌

冀X12345|蓝牌

相关推荐
期待のcode32 分钟前
Spring框架1—Spring的IOC核心技术1
java·后端·spring·架构
葵野寺40 分钟前
【RelayMQ】基于 Java 实现轻量级消息队列(七)
java·开发语言·网络·rabbitmq·java-rabbitmq
书院门前细致的苹果1 小时前
JVM 全面详解:深入理解 Java 的核心运行机制
java·jvm
上官浩仁1 小时前
springboot excel 表格入门与实战
java·spring boot·excel
Hello.Reader2 小时前
从零到一上手 Protocol Buffers用 C# 打造可演进的通讯录
java·linux·c#
树码小子2 小时前
Java网络初识(4):网络数据通信的基本流程 -- 封装
java·网络
稻草人想看远方3 小时前
GC垃圾回收
java·开发语言·jvm
en-route3 小时前
如何在 Spring Boot 中指定不同的配置文件?
java·spring boot·后端
百锦再3 小时前
在 CentOS 系统上实现定时执行 Python 邮件发送任务
java·linux·开发语言·人工智能·python·centos·pygame
echoyu.4 小时前
消息队列-kafka完结
java·分布式·kafka