Javascript 单个正则表达式匹配范围(1999-2010)还是仅匹配单个值(2010)?

Javascript 单个正则表达式匹配范围(1999-2010)还是仅匹配单个值(2010)?,javascript,regex,Javascript,Regex,总的来说,我认为我还没有找到解决这个问题的通用方法。如何匹配可以是一个范围或单个值的字符串 假设我想匹配[复杂]日期: 1999-2010 公元前323年-公元前100年 公元前323年 一九九五至九九年度 公元前323-322年 可以分析这两种情况的通用正则表达式“模板”是什么: 开始/结束日期(如果存在) 否则,只有一次约会 为了配合“1999-2010”,你可以 /(\d+\s*)-(\s*\d+)/ // where $1 and $2 are start and end 要匹配更

总的来说,我认为我还没有找到解决这个问题的通用方法。如何匹配可以是一个范围或单个值的字符串

假设我想匹配[复杂]日期:

  • 1999-2010
  • 公元前323年-公元前100年
  • 公元前323年
  • 一九九五至九九年度
  • 公元前323-322年
可以分析这两种情况的通用正则表达式“模板”是什么:

  • 开始/结束日期(如果存在)
  • 否则,只有一次约会
  • 为了配合“1999-2010”,你可以

    /(\d+\s*)-(\s*\d+)/ // where $1 and $2 are start and end
    
    要匹配更复杂的“323 BCE-100 CE”,您可以

    /(\w+\s*\w+)\s*-\s*(\w+\s*\w+)/
    
    /\w+\s*\w+/
    
    为了匹配更简单的“公元前323年”,你可以

    /(\w+\s*\w+)\s*-\s*(\w+\s*\w+)/
    
    /\w+\s*\w+/
    

    但是,如何编写一个表达式,首先检查范围(323 BCE-100 CE),如果不存在,则检查单个值(323 BC),该值也可以处理上面列表中的其他示例?

    ,方法是将匹配的后一部分设置为可选

    /(\w+\s*\w+)(?:\s*-\s*(\w+\s*\w+))?/
    
    示例(JavaScript)

    注意,外部可选部分被设置为非匹配,因此结果数组只包含您感兴趣的子匹配项


    也可以从效率角度加强模式,例如,寻找数字而不是任何字母数字,并且只允许单个空格(如果可以接受的话),而不是零或更多。

    只是为了加入另一种可能按照您希望的方式工作的模式

    ((\d+)([A-Za-z]+|)((-124;-)\ d+([A-Za-z]+|)|)


    与乌特卡诺斯的模式一样,这可能需要一些收紧以不匹配其他任何东西。

    您可能正在寻找类似的东西:

    var pattern = /(\d+)(\s*(\w+))?(\s*-\s*(\d+)(\s*(\w+))?)?/;
    var strings = [
        '1999 - 2010',
        '323 BCE - 100 CE',
        '323 BC',
        '1995-99',
        '323 - 322 BC'
    ];
    
    for (var i=0, s; s = strings[i]; i++) {
        var m  = s.match(pattern);
        console.log(
            m[1], // beginning year
            m[3], // beginning b/c/e
            m[5], // end year
            m[7]  // end b/c/e
        );
    }
    
    哪个输出

    1999  undefined  2010       undefined
    323   BCE        100        CE
    323   BC         undefined  undefined
    1995  undefined  99         undefined
    323   undefined  322        BC
    

    这里的诀窍是理解
    (组)
    使
    (组)
    成为可选的。与此类似,
    (foo)+
    (foo){3}
    可用于使组至少匹配一次或正好匹配三次

    (foo)
    默认情况下是捕获组。这意味着它们的结果将包含在字符串#match()返回的数组中。您可以将组标记为非捕获,如下所示:
    (?:不会被捕获)
    。这样,我们可以进一步修改上述模式:

    var pattern = /(\d+)(?:\s*(\w+))?(?:\s*-\s*(\d+)(?:\s*(\w+))?)?/;
    for (var i=0, s; s = strings[i]; i++) {
        var m  = s.match(pattern);
        console.log(m[1], m[2], m[3], m[4]);
    }