var pattern = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
var pattern = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
var urlRegex = new RegExp(
/(?:(?:(https?|ftp):)?\/\/)/.source // protocol
+ /(?:([^:\n\r]+):([^@\n\r]+)@)?/.source // user:pass
+ /(?:(?:www.)?([^/\n\r]+))/.source // domain
+ /(\/[^?\n\r]+)?/.source // request
+ /(\?[^#\n\r]*)?/.source // query
+ /(#?[^\n\r]*)?/.source // anchor
);
或者,如果你想避免重复使用 .source
属性,可以使用 Array.map()
函数:
var urlRegex = new RegExp([
/(?:(?:(https?|ftp):)?\/\/)/, // protocol
/(?:([^:\n\r]+):([^@\n\r]+)@)?/, // user:pass
/(?:(?:www.)?([^/\n\r]+))/, // domain
/(\/[^?\n\r]+)?/, // request
/(\?[^#\n\r]*)?/, // query
/(#?[^\n\r]*)?/, // anchor
].map(function (r) { return r.source; }).join(''));
.map(r => r.source)
。combineRegex = (...regex) => new RegExp(regex.map(r => r.source).join(""))
用法:combineRegex(/regex1/, /regex2/, ...)
- Scindixnew RegExp()
来创建表达式:var myRE = new RegExp (['^(([^<>()[\]\\.,;:\\s@\"]+(\\.[^<>(),[\]\\.,;:\\s@\"]+)*)',
'|(\\".+\\"))@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.',
'[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\\.)+',
'[a-zA-Z]{2,}))$'].join(''));
注意事项:
将 表达式字面量 转换为字符串时,需要转义所有反斜杠,因为在解析 字符串字面量 时会自动消耗掉反斜杠。 (详见 Kayo 的评论.)
RegExp
函数接受一个修饰符作为第二个参数。
/regex/g
=> new RegExp('regex', 'g')
[新增 ES20xx 特性 (模板标签)]
在 ES20xx 中,你可以使用模板标签。请查看代码片段。
注意:
\s
、\s+
、\s{1,x}
, \t
, \n
等)。(() => {
const createRegExp = (str, opts) =>
new RegExp(str.raw[0].replace(/\s/gm, ""), opts || "");
const yourRE = createRegExp`
^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|
(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|
(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$`;
console.log(yourRE);
const anotherLongRE = createRegExp`
(\byyyy\b)|(\bm\b)|(\bd\b)|(\bh\b)|(\bmi\b)|(\bs\b)|(\bms\b)|
(\bwd\b)|(\bmm\b)|(\bdd\b)|(\bhh\b)|(\bMI\b)|(\bS\b)|(\bMS\b)|
(\bM\b)|(\bMM\b)|(\bdow\b)|(\bDOW\b)
${"gi"}`;
console.log(anotherLongRE);
})();
//
定义)并将其粘贴为RegExp构造函数的字符串参数。这是因为在评估“字符串文字”时反斜杠字符会被消耗。例如:/Hey\sthere/
不能被替换为 new RegExp("Hey\sthere")
。而应该替换为 new RegExp("Hey\\sthere")
注意额外的反斜杠!因此,我更喜欢将长的正则表达式文字留在一行上。 - KayoRegExp
,让整个过程更易于理解。 - Chris Krycho使用 new RegExp
中的字符串很麻烦,因为必须转义所有反斜杠。您可以编写较小的正则表达式并将它们连接起来。
让我们拆分这个正则表达式。
/^foo(.*)\bar$/
稍后我们将使用一个函数来使事情变得更加美观
function multilineRegExp(regs, options) {
return new RegExp(regs.map(
function(reg){ return reg.source; }
).join(''), options);
}
现在让我们开始摇滚吧
var r = multilineRegExp([
/^foo/, // we can add comments too
/(.*)/,
/\bar$/
]);
由于构建正则表达式需要成本,因此尝试仅构建一次真实的正则表达式,然后重复利用。
multilineRegExp([/a|b/, /c|d])
的结果是 /a|bc|d/
,而你想要的是 (a|b)(c|d)
。 - quezakmultilineRegExp([/a (/, /cold/, /|hot/, /) drink/])
。 - ProblemsLoop//build regexes without worrying about
// - double-backslashing
// - adding whitespace for readability
// - adding in comments
let clean = (piece) => (piece
.replace(/((^|\n)(?:[^\/\\]|\/[^*\/]|\\.)*?)\s*\/\*(?:[^*]|\*[^\/])*(\*\/|)/g, '$1')
.replace(/((^|\n)(?:[^\/\\]|\/[^\/]|\\.)*?)\s*\/\/[^\n]*/g, '$1')
.replace(/\n\s*/g, '')
);
window.regex = ({raw}, ...interpolations) => (
new RegExp(interpolations.reduce(
(regex, insert, index) => (regex + insert + clean(raw[index + 1])),
clean(raw[0])
))
);
使用这个工具,你现在可以像这样编写正则表达式:
let re = regex`I'm a special regex{3} //with a comment!`;
输出
/I'm a special regex{3}/
'123hello'
.match(regex`
//so this is a regex
//here I am matching some numbers
(\d+)
//Oh! See how I didn't need to double backslash that \d?
([a-z]{1,3}) /*note to self, this is group #2*/
`)
[2]
输出 hel
,很整洁!
如果我需要实际搜索一个换行符怎么办?那就使用 \n
呗!
正在处理我的 Firefox 和 Chrome 浏览器。
好的,“那么复杂一点的呢?”
当然,这是我正在开发的一个对象解构JS解析器的一部分:
regex`^\s*
(
//closing the object
(\})|
//starting from open or comma you can...
(?:[,{]\s*)(?:
//have a rest operator
(\.\.\.)
|
//have a property key
(
//a non-negative integer
\b\d+\b
|
//any unencapsulated string of the following
\b[A-Za-z$_][\w$]*\b
|
//a quoted string
//this is #5!
("|')(?:
//that contains any non-escape, non-quote character
(?!\5|\\).
|
//or any escape sequence
(?:\\.)
//finished by the quote
)*\5
)
//after a property key, we can go inside
\s*(:|)
|
\s*(?={)
)
)
((?:
//after closing we expect either
// - the parent's comma/close,
// - or the end of the string
\s*(?:[,}\]=]|$)
|
//after the rest operator we expect the close
\s*\}
|
//after diving into a key we expect that object to open
\s*[{[:]
|
//otherwise we saw only a key, we now expect a comma or close
\s*[,}{]
).*)
$`
它输出/^\s*((\})|(?:[,{]\s*)(?:(\.\.\.)|(\b\d+\b|\b[A-Za-z$_][\w$]*\b|("|')(?:(?!\5|\\).|(?:\\.))*\5)\s*(:|)|\s*(?={)))((?:\s*(?:[,}\]=]|$)|\s*\}|\s*[{[:]|\s*[,}{]).*)$/
可以用一个小示例来运行它吗?
let input = '{why, hello, there, "you huge \\"", 17, {big,smelly}}';
for (
let parsed;
parsed = input.match(r);
input = parsed[parsed.length - 1]
) console.log(parsed[1]);
成功输出{{}}
{why
, hello
, there
, "you huge \""
, 17
,
{big
,smelly
}
}
注意成功捕获引用字符串。
我在Chrome和Firefox上测试过,效果很好!
如果你好奇我在做什么, 可以查看演示。
虽然它只适用于Chrome,因为Firefox不支持反向引用或命名组。因此请注意,本答案中给出的示例实际上是一个被削弱的版本,可能会轻易地被欺骗而接受无效的字符串。
这里有很好的答案,但为了完整性,应该提到JavaScript通过原型链继承的核心特性。类似这样的东西说明了这个想法:
RegExp.prototype.append = function(re) {
return new RegExp(this.source + re.source, this.flags);
};
let regex = /[a-z]/g
.append(/[A-Z]/)
.append(/[0-9]/);
console.log(regex); //=> /[a-z][A-Z][0-9]/g
.append
时都会创建编译RegExp对象,因此其他答案一次性编译给定的组合数组略好。我想差异微不足道,但值得注意。 - ProblemsLoop上述正则表达式缺少一些反斜杠,导致其无法正常工作。因此,我编辑了该正则表达式。请考虑使用此正则表达式进行电子邮件验证,其有效率高达99.99%。
let EMAIL_REGEXP =
new RegExp (['^(([^<>()[\\]\\\.,;:\\s@\"]+(\\.[^<>()\\[\\]\\\.,;:\\s@\"]+)*)',
'|(".+"))@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.',
'[0-9]{1,3}\])|(([a-zA-Z\\-0-9]+\\.)+',
'[a-zA-Z]{2,}))$'].join(''));
var pattern = new RegExp('^(([^<>()[\]\\.,;:\s@\"]+' +
'(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@' +
'((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|' +
'(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$');
我尝试通过封装所有内容并实现支持拆分捕获组和字符集的方法来改进korun的答案-使这种方法更加通用。
要使用此代码段,您需要调用可变参数函数combineRegex
,其参数是您需要组合的正则表达式对象。它的实现可以在底部找到。
直接拆分捕获组是不行的,因为这样会让一些部分只有一个括号。您的浏览器将出现异常。
相反,我只是将捕获组的内容传递到数组中。当combineRegex
遇到数组时,括号会自动添加。
此外,量词需要跟在某些内容之后。如果由于某种原因需要在量词之前拆分正则表达式,则需要添加一对括号。这些将自动删除。重点是空捕获组相当无用,通过这种方式,量词就有了参考物。同样的方法也可以用于像非捕获组(/(?:abc)/
成为[/()?:abc/]
)之类的东西。
以下是一个简单的示例:
var regex = /abcd(efghi)+jkl/;
would become:
var regex = combineRegex(
/ab/,
/cd/,
[
/ef/,
/ghi/
],
/()+jkl/ // Note the added '()' in front of '+'
);
{"":[regex1, regex2, ...]}
)代替数组([regex1, regex2, ...]
)。键的内容可以是任何内容,只要对象只包含一个键即可。请注意,如果第一个字符可能被解释为量词符号,则必须使用]
作为虚拟开头,而不是()
。例如,/[+?]/
变成{"":[/]+?/]}
。
Here is the snippet and a more complete example:
function combineRegexStr(dummy, ...regex)
{
return regex.map(r => {
if(Array.isArray(r))
return "("+combineRegexStr(dummy, ...r).replace(dummy, "")+")";
else if(Object.getPrototypeOf(r) === Object.getPrototypeOf({}))
return "["+combineRegexStr(/^\]/, ...(Object.entries(r)[0][1]))+"]";
else
return r.source.replace(dummy, "");
}).join("");
}
function combineRegex(...regex)
{
return new RegExp(combineRegexStr(/^\(\)/, ...regex));
}
//Usage:
//Original:
console.log(/abcd(?:ef[+A-Z0-9]gh)+$/.source);
//Same as:
console.log(
combineRegex(
/ab/,
/cd/,
[
/()?:ef/,
{"": [/]+A-Z/, /0-9/]},
/gh/
],
/()+$/
).source
);
var pattenString = "^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|"+
"(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|"+
"(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$";
var patten = new RegExp(pattenString);
个人而言,我会选择一个不那么复杂的正则表达式:
/\S+@\S+\.\S+/
var box1 = "([^<>()[\]\\\\.,;:\s@\"]+(\\.[^<>()[\\]\\\\.,;:\s@\"]+)*)";
var box2 = "(\".+\")";
var host1 = "(\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\])";
var host2 = "(([a-zA-Z\-0-9]+\\.)+[a-zA-Z]{2,})";
var regex = new RegExp("^(" + box1 + "|" + box2 + ")@(" + host1 + "|" + host2 + ")$");
/\S+@\S+\.\S+/
? - Bart Kiers