总的来说,我认为我没有遇到过这个问题的通用解决方案。如何匹配可以是范围的字符串,或者只是一个值?
说我想匹配[复杂]日期:
可以解析这两种情况的一般正则表达式“模板”是什么:
要匹配“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+)/
为了匹配更简单的“323 BC”,你可以做到
/\w+\s*\w+/
但是如何编写一个首先检查范围(323 BCE-100 CE)的表达式,如果不存在,则检查单个值(323 BC),还可以处理上面列表中的其他示例吗?
答案 0 :(得分:2)
通过使比赛的后半部分可选。
/(\w+\s*\w+)(?:\s*-\s*(\w+\s*\w+))?/
示例(JavaScript)
"1900 - 2000".match(/(\w+\s*\w+)(?:\s*-\s*(\w+\s*\w+))?/);
//["1900 - 2000", "1900", "2000"]
"1900 BC".match(/(\w+\s*\w+)(?:\s*-\s*(\w+\s*\w+))?/);
//["1900 BC", "1900 BC", undefined]
请注意,外部可选部分是不匹配的,因此结果数组仅包含您感兴趣的子匹配。
以效率方式收紧模式也是一个想法,例如:寻找数字而不是任何字母数字,并且只允许单个空格(如果这是可接受的)而不是零或更多。
答案 1 :(得分:0)
只是投入另一种可能按你想要的方式运作的模式;
((\d+)( [A-Za-z]+|))((-| - )\d+( [A-Za-z]+|)|)
与Utkanos的模式一样,这可能需要收紧一些而不是匹配任何其他内容。
答案 2 :(得分:0)
你可能正在寻找这样的东西:
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
这里的诀窍是要了解(group)?
使(group)
成为可选项。与此类似,(foo)+
和(foo){3}
可用于使群组匹配至少一次或恰好三次。
默认情况下,组(foo)
是捕获组。这意味着它们的结果将包含在String#match()返回的数组中。您可以将组标记为非捕获,如下所示:(?:wont-be-captured)
。有了这个,我们可以进一步修改上述模式:
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]);
}