js 正则校验车架号VIN

正则要求:

  1. 由大写字母和数字组成,长度17位;
  2. 字母不会出现O、Q、I三个字母;
  3. 第9位只能是【0-9】的数字和字母X;
  4. 第13-17位只能是数字;

根据百度、谷歌只搜搜到这个,还请各位大佬们赐教
现在只实现了1,2两个条件;如下:
let reg=/^[A-HJ-NPR-Z\d]{17}$/

阅读 9.9k
3 个回答

根据规则一个个罗列出来不就是了?/^[A-HJ-NPR-Z\d]{8}[X\d][A-HJ-NPR-Z\d]{3}\d{5}$/

简单的是/^[A-HJ-NPR-Z\d]{8}[X\d][A-HJ-NPR-Z\d]{3}\d{5}$/这个规则,不过估计类似身份证号,里面应该还包括校验位,估计校验位就是第9位,所以完整判别估计不能只由规则式判定,还需要检测校验位。

检索到 https://baijiahao.baidu.com/s...
所以完整的还需要进一步进行判断。

这里有校验位计算方法 https://blog.csdn.net/shenhon...

var checkVIN=function(VIN){
    if(typeof(VIN)!='string') return false;
    if(VIN.length!=17) return false;
    VIN=VIN.toUpperCase();
    RE==/^[A-HJ-NPR-Z\d]{8}[X\d][A-HJ-NPR-Z\d]{3}\d{5}$/
    if(!RE.test(VIN)) return false;
    let cOT={
        '0':0,'1':1,'2':2,'3':3,'4':4,'5':5,'6':6,'7':7,
        '8':8,'9':9,'A':1,'B':2,'C':3,'D':4,'E':5,'F':6,
        'G':7,'H':8,'J':1,'K':2,'L':3,'M':4,'N':5,'P':7,
        'R':9,'S':2,'T':3,'U':4,'V':5,'W':6,'X':7,'Y':8,
        'Z':9
    };
    let xWT=[8,7,6,5,4,3,2,10,0,9,8,7,6,5,4,3,2]; // 因为第9位权重为0,所以原来是什么字符不影响结果,可以方便后面计算
    let sum=0;
    VINs=VIN.split('');
    for(let i=0;i<17;i++){
        sum=sum + cOT[ VINs[i] ] * xWT[i];
    }
    let cT=['0','1','2','3','4','5','6','7','8','9','X'];
    if( cT[ (sum%11) ] == VINs[8]) return true;
    return false;
}

@xdsnet 的回答已经很全面了,先用正则表达式快速检查,再做校验。我这里只是对代码做一个纯粹的技术探讨。

关于 cOT 的生成

手写太累,可以

const cOT = (() => {
    const entries = [
        "0123456789",
        " ABCDEFGH",
        " JKLMNOPQR",
        "  STUVWXYZ"
    ].flatMap(
        // Array.from 把字符串拆分成字符数组(主要是手写字符数组太累)
        // 根据字符位置生成 entry,比如 ['J', 1]
        // 完了进行 flat,把多组数组扁平化
        s => Array.from(s).map((c, i) => [c, i])
    );

    // 从 entires 生成对象,这个对象的键包含了空格、I、O 和 Q
    // 如果将上面的 IOQ 替换成空格,这里多的就只有空格
    const map = Object.fromEntries(entries);
    // 删除多余的键(其实不删也没关系,因为之前已经用正则已将这些字符排除掉了)
    return Array.from(" IOQ").reduce((m, c) => (delete m[c], m), map);
})();

这段代码只在初始化的时候执行一次,对效率没啥影响。如果还是想直接定义成常量,将上述代码的执行结果在控制台中用 JSON.stringify(cOT) 输出就是。

关于计算 SUM

效率并不如原生循环,只是把计算过程封装在一句话里。用 IIFE 也可以达到同样的效果。

const sum = Array.from(VIN)
    .map((c, i) => cOT[c] * xWT[i])
    .reduce((s, v) => s + v, 0);

关于 10 => 'X'

直接用数组很直接,关无毛病。

这是个时间换空间的写法(其实对于这点空间,没啥卵用),

const vcode = (mod => mod === 10 ? "X" : mod.toString())(sum % 11);
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏