Javascript Regex使用可选的pre和post字符串验证多种格式

Javascript Regex使用可选的pre和post字符串验证多种格式,javascript,regex,Javascript,Regex,我试图以最有效的方式验证两种不同的方法来标识位置字符串,但其中一种方法可能有轻微的变化,并且在主字符串前后都有一组字符 有效值: 第一 二号 上面的数字3在主字符串之前可以有3位数字,在主字符串之后可以有2位数字(或不) 在这5个附加字符中,以下是规则: 第一-始终为1或2 第二-始终为0 第三-0至9 第四名-始终为0 5-0至9 因此,我认为分别是[1-2]0[0-9]和0[0-9]。还要注意,前3位数字与后2位数字相关,反之亦然。前3位只能在最后2位存在时存在,后2位只能在前3位存在时

我试图以最有效的方式验证两种不同的方法来标识位置字符串,但其中一种方法可能有轻微的变化,并且在主字符串前后都有一组字符

有效值:

第一 二号 上面的数字3在主字符串之前可以有3位数字,在主字符串之后可以有2位数字(或不) 在这5个附加字符中,以下是规则:
  • 第一-始终为1或2
  • 第二-始终为0
  • 第三-0至9
  • 第四名-始终为0
  • 5-0至9
因此,我认为分别是
[1-2]0[0-9]
0[0-9]
。还要注意,前3位数字与后2位数字相关,反之亦然。前3位只能在最后2位存在时存在,后2位只能在前3位存在时存在

这给我们提供了以下不应匹配的无效字符串: 这是我的两个主要号码的代码 我只是假设在第一次验证中使用案例1的#3,因为我不确定如何使用空格、破折号或无效。

/^([1-2]0[0-9])?[0-9]{2}-[0-9]{3}-[0-9]{2}-[0-9]{2}[-]W[0-9](0[0-9])?$/

对于第一个,以及

/^([1-2]0[0-9])?[A-D][0-9][0-9]{3}[A-L][0-9]{3}[A-p][0-9]{2}(0[0-9])?$/


第二次。我对正则表达式不太在行,所以我完全有可能把某个地方搞砸了。

根据您对@SamuelReid答案的评论中的要求,正则表达式将变得丑陋。当两个字符串需求彼此依赖于开/关(在字符串的相对侧)时,这会变得很困难

正则表达式: (2)在上述两名人士的代码><<<码>////////以下以下以下两名::::::[12[12]0岁以下以下以下以下的主要代码:::::::::::::[3名名:::::)及(3名:)及(3名:::)及(3名::::::)3{{{{{{{33 3}{{{{{3}[2}[3}}}[[)3名名名名[3}[3}[3}........上述两两名名名:::::::::::[A-d(A-d)及[A-d(A-d)及[A-d[A-d[A-d[[[A-d....................................}))$/

格式良好/易于阅读的版本: (在空白处添加了
[]
,以强调它们,因为它们在自由间隔模式(x标志)中很重要并且丢失了——js中不支持这种AFAIK)

正如您从“易于阅读的版本”中所看到的,基本正则表达式只需在其中一个表达式上添加两次
[12]0\d[]
[]0\d


如果需要在字符串的中间匹配,则简单地在ReXEX的两端交换< <代码> ^ 和<代码> $< /Case>锚,代码< > b>代码>:

带有
\b
边界的正则表达式,而不是
^
$

(2)及/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////2})\b/

第一个数字类型可以与下面的表达式匹配,这与您已有的表达式非常相似:

/d{2}-\d{2}-\d{3}-\d{2}[ -]?W\d/
                       ^^^^^ 
                       added
我正在使用字符集,
[-]?
,它可以选择匹配空格或连字符

额外字符

匹配左侧:

/^[12]0\d /
右半部分:

/ 0\d$/
现在大家一起:

/^(?:(?:[12]0\d )(?:\d{2}-\d{2}-\d{3}-\d{2}[ -]?W\d|[A-D] \d{3} [A-L] \d{3}[A-P]\d{2})(?: 0\d)|(?:\d{2}-\d{2}-\d{3}-\d{2}[ -]?W\d|[A-D] \d{3} [A-L] \d{3}[A-P]\d{2}))$/
让我们稍微整理一下:

var w1 = '\\d{2}-\\d{2}-\\d{3}-\\d{2}[ -]?W\\d',
w2 = '[A-D] \\d{3} [A-L] \\d{3}[A-P]\\d{2}',
words = '(?:' + w1 + '|' + w2 + ')',
prefix = '[12]0\\d ',
suffix = ' 0\\d',
re;

re = new RegExp('^(?:' + prefix + words + suffix + '|' + words + ')$');

这真的不是那么糟糕(尽管肯定是一个大的正则表达式)。这应包括图案和开头或结尾的其他可能数字

以下是您需要的模式:

var re = new RegExp("^([1-2]0\\d )?(\\d{2}-\\d{2}-\\d{3}-\\d{2}[\- ]?W\\d|[A-D] \\d{3} [A-L] \\d{3}[A-P]\\d{2})( 0\\d)?$");
。或者,或者:

var re = /^([1-2]0\d )?(\d{2}-\d{2}-\d{3}-\d{2}[\- ]?W\d|[A-D] \d{3} [A-L] \d{3}[A-P]\d{2})( 0\d)?$/
代码的其余部分应该可以很好地使用它

编辑:基于我对“要么全有要么全无”的新理解,我更新了我的方法。我将基于由公共模式构造的两个正则表达式模式进行两个测试

var sCorePattern = "(\\d{2}-\\d{2}-\\d{3}-\\d{2}[\- ]?W\\d|[A-D] \\d{3} [A-L] \\d{3}[A-P]\\d{2})";
var sSecondaryPattern = "[1-2]0\\d " + sCorePattern + " 0\\d";

var regCorePattern = new RegExp("^" + sCorePattern + "$");
var regSecondaryPattern = new RegExp("^" + sSecondaryPattern + "$");

if (regCorePattern.test(s) || regSecondaryPattern.test(s)) {
    . . . do stuff . . .
}
else {
    . . . do other stuff . . .
}

对我来说,它是效率和重用的良好结合,同时又不牺牲可读性

您并不是真的想构建一个大的regexp 一次成功。它将很难阅读和维护。及 当您的开发伙伴不得不调试时,他们会讨厌您 这是当你在坎昆度假时喝着玛格丽塔酒的时候 海滩

因此,我建议将其分解为清晰、有意义的部分 块(你必须在这里使用你的判断:这是你的 域)。也许是这样的

var prefix = '([12]0[0-9] )';
var suffix = '( 0[0-9])';
// ? optionally matches the preceding item.
// And don't forget to escape backslashes when creating
// a regexp from a string.
var num1 = '\\d{2}-\\d{2}-\\d{3}-\\d{2}[- ]?W\\d';
var num2 = '[A-D] [0-9]{3} [A-L] [0-9]{3}[A-P][0-9]{2}';
var numbers = '(' + num1 + '|' + num2 + ')';
var pattern = '^(' + prefix + numbers + suffix + '|' + numbers + ')$';
// Instead of creating a large regexp literal all in
// one go, you can build up the regexp pattern from strings,
// and then use RegExp(pattern) to make a regexp instance.
var rx = RegExp(pattern);
现在您可以使用
rx
来匹配您的输入 数字。请随意使用更有意义的变量名

但不要把它放在那里。这是一个迫切需要解决的问题 一些测试

var testcases = [
    {
        name: 'Number 1',
        tests: [
            {input: '14-36-085-17 W6', expected: true},
            {input: '14-36-085-17-W6', expected: true},
            {input: '14-36-085-17W6', expected: true}
        ]
    },
    {
        name: 'Number 2',
        tests: [
            {input: 'D 096 H 094A15', expected: true}
        ]
    },
    {
        name: 'Number 3',
        tests: [
            {input: '100 14-36-085-17W6 00', expected: true},
            {input: '200 D 096 H 094A15 00', expected: true},
            {input: '100 14-36-085-17W6', expected: false},
            {input: '14-36-085-17W6 00', expected: false}
        ]
    }
];
让我们试试我们的regexp。我只是在做这些 在Chrome的开发者控制台中进行测试(F12)

和输出

Number 1 14-36-085-17 W6 result: match [pass] 14-36-085-17-W6 result: match [pass] 14-36-085-17W6 result: match [pass] Number 2 D 096 H 094A15 result: match [pass] Number 3 100 14-36-085-17W6 00 result: match [pass] 200 D 096 H 094A15 00 result: match [pass] 100 14-36-085-17W6 result: no match [pass] 14-36-085-17W6 00 result: no match [pass] 第一 14-36-085-17 W6结果:匹配[通过] 14-36-085-17-W6结果:匹配[通过] 14-36-085-17W6结果:匹配[通过] 二号 D 096 H 094A15结果:匹配[通过] 三号 100 14-36-085-17W6 00结果:匹配[通过] 200 D 096 H 094A15 00结果:匹配[通过] 100 14-36-085-17W6结果:不匹配[通过] 14-36-085-17W6 00结果:不匹配[通过] 太好了。通过测试让你有信心做出改变, 并保证在你离开时没有损坏任何东西 做这给了我信心,我不会给你机会 愚蠢的回答。如果你搜索一下,你会发现有很多 提供的自动化单元测试框架将 编写测试更容易。我给你的只是初步的 例子。但是,当你开始跑步时,你就会获得巨大的胜利 自动化测试;之后的一切都是精致

顺便说一下,这些测试只是您提供的示例 在这个问题上,你可以说是有效的,也可以说是无效的(谢谢你!)。我想要 建议您找到更多的示例,并在此基础上进行构建。 希望我已经给了你足够多的建议,你可以 如果我所做的事情没有结果,就从这里开始 无论如何都要足够

对于regexp答案来说,这似乎有点过头了,但是 我不能毫无顾忌地建议你使用一个巨大的 用于验证的regexp,但不推荐某些机器 使事情易于管理


进一步阅读

如您所说,执行“空格、破折号或无效”
var re = new RegExp("^([1-2]0\\d )?(\\d{2}-\\d{2}-\\d{3}-\\d{2}[\- ]?W\\d|[A-D] \\d{3} [A-L] \\d{3}[A-P]\\d{2})( 0\\d)?$");
var re = /^([1-2]0\d )?(\d{2}-\d{2}-\d{3}-\d{2}[\- ]?W\d|[A-D] \d{3} [A-L] \d{3}[A-P]\d{2})( 0\d)?$/
var sCorePattern = "(\\d{2}-\\d{2}-\\d{3}-\\d{2}[\- ]?W\\d|[A-D] \\d{3} [A-L] \\d{3}[A-P]\\d{2})";
var sSecondaryPattern = "[1-2]0\\d " + sCorePattern + " 0\\d";

var regCorePattern = new RegExp("^" + sCorePattern + "$");
var regSecondaryPattern = new RegExp("^" + sSecondaryPattern + "$");

if (regCorePattern.test(s) || regSecondaryPattern.test(s)) {
    . . . do stuff . . .
}
else {
    . . . do other stuff . . .
}
var prefix = '([12]0[0-9] )';
var suffix = '( 0[0-9])';
// ? optionally matches the preceding item.
// And don't forget to escape backslashes when creating
// a regexp from a string.
var num1 = '\\d{2}-\\d{2}-\\d{3}-\\d{2}[- ]?W\\d';
var num2 = '[A-D] [0-9]{3} [A-L] [0-9]{3}[A-P][0-9]{2}';
var numbers = '(' + num1 + '|' + num2 + ')';
var pattern = '^(' + prefix + numbers + suffix + '|' + numbers + ')$';
// Instead of creating a large regexp literal all in
// one go, you can build up the regexp pattern from strings,
// and then use RegExp(pattern) to make a regexp instance.
var rx = RegExp(pattern);
var testcases = [
    {
        name: 'Number 1',
        tests: [
            {input: '14-36-085-17 W6', expected: true},
            {input: '14-36-085-17-W6', expected: true},
            {input: '14-36-085-17W6', expected: true}
        ]
    },
    {
        name: 'Number 2',
        tests: [
            {input: 'D 096 H 094A15', expected: true}
        ]
    },
    {
        name: 'Number 3',
        tests: [
            {input: '100 14-36-085-17W6 00', expected: true},
            {input: '200 D 096 H 094A15 00', expected: true},
            {input: '100 14-36-085-17W6', expected: false},
            {input: '14-36-085-17W6 00', expected: false}
        ]
    }
];
testcases.forEach(function(testcase){
    console.log(testcase.name);
    testcase.tests.forEach(function(test){
        var result = rx.test(test.input);
        console.log(test.input + '  result: ' +
                (result ? 'match' : 'no match') +
                (result === test.expected ? ' [pass]' : ' [**FAIL**]'));
    });
    console.log('');
});
Number 1 14-36-085-17 W6 result: match [pass] 14-36-085-17-W6 result: match [pass] 14-36-085-17W6 result: match [pass] Number 2 D 096 H 094A15 result: match [pass] Number 3 100 14-36-085-17W6 00 result: match [pass] 200 D 096 H 094A15 00 result: match [pass] 100 14-36-085-17W6 result: no match [pass] 14-36-085-17W6 00 result: no match [pass]