我正在用 HTML 和 JavaScript 设计一个正则表达式测试器。用户将输入一个正则表达式、一个字符串,并通过单选按钮选择他们想要测试的函数(例如搜索、匹配、替换等),当使用指定参数运行该函数时,程序将显示结果。自然会有额外的文本框来替换额外的参数等。
我的问题是从用户那里获取字符串并将其转换为正则表达式。如果我说他们不需要在输入的正则表达式周围有 //
,那么他们就不能设置标志,例如 g
和 i
。所以他们必须在表达式周围有 //
,但我怎样才能将该字符串转换为正则表达式?它不能是文字,因为它是一个字符串,并且我不能将它传递给 RegExp 构造函数,因为它不是没有 //
的字符串。有没有其他方法可以将用户输入字符串变成正则表达式?我是否必须用 //
解析正则表达式的字符串和标志,然后以另一种方式构造它?我应该让他们输入一个字符串,然后分别输入标志吗?
使用 RegExp object constructor 从字符串创建正则表达式:
var re = new RegExp("a|b", "i");
// same as
var re = /a|b/i;
var flags = inputstring.replace(/.*\/([gimy]*)$/, '$1');
var pattern = inputstring.replace(new RegExp('^/(.*?)/'+flags+'$'), '$1');
var regex = new RegExp(pattern, flags);
或者
var match = inputstring.match(new RegExp('^/(.*?)/([gimy]*)$'));
// sanity check here
var regex = new RegExp(match[1], match[2]);
/\/
这样的无效输入。
/foo/ggggg
。在第一个示例中,您可以将 flags
替换更改为 replace('/.*\/(?!.*(.).*\1)([gimy]*)$/', '$2')
。或者对第二个示例 ^\/(.*)\/(?!.*(.).*\2)([gimy]*)$
使用以下正则表达式,什么会将标志放在匹配组 3 中。
这是一个单行:str.replace(/[|\\{}()[\]^$+*?.]/g, '\\$&')
我从 escape-string-regexp NPM 模块得到它。
尝试一下:
escapeStringRegExp.matchOperatorsRe = /[|\\{}()[\]^$+*?.]/g;
function escapeStringRegExp(str) {
return str.replace(escapeStringRegExp.matchOperatorsRe, '\\$&');
}
console.log(new RegExp(escapeStringRegExp('example.com')));
// => /example\.com/
使用带有标志支持的标记模板文字:
function str2reg(flags = 'u') {
return (...args) => new RegExp(escapeStringRegExp(evalTemplate(...args))
, flags)
}
function evalTemplate(strings, ...values) {
let i = 0
return strings.reduce((str, string) => `${str}${string}${
i < values.length ? values[i++] : ''}`, '')
}
console.log(str2reg()`example.com`)
// => /example\.com/u
使用 JavaScript RegExp object constructor。
var re = new RegExp("\\w+");
re.test("hello");
您可以将标志作为第二个字符串参数传递给构造函数。有关详细信息,请参阅文档。
在我的情况下,用户输入 somethimes 被分隔符包围,有时没有。因此我添加了另一个案例..
var regParts = inputstring.match(/^\/(.*?)\/([gim]*)$/);
if (regParts) {
// the parsed pattern had delimiters and modifiers. handle them.
var regexp = new RegExp(regParts[1], regParts[2]);
} else {
// we got pattern string without delimiters
var regexp = new RegExp(inputstring);
}
.split()
函数而不是长的正则表达式字符串。 regParts = inputstring.split('/')
这将使 regParts[1]
成为正则表达式字符串,而 regParts[2]
成为分隔符(假设正则表达式的设置是 /.../gim
)。您可以检查是否有带有 regParts[2].length < 0
的分隔符。
/
function stringToRegex(s, m) { return (m = s.match(/^(.)(.*?)\1([gimsuy]*)$/)) ? new RegExp(m[2], m[3]) : new RegExp(s); }
尝试使用以下功能:
const stringToRegex = str => {
// Main regex
const main = str.match(/\/(.+)\/.*/)[1]
// Regex options
const options = str.match(/\/.+\/(.*)/)[1]
// Compiled regex
return new RegExp(main, options)
}
你可以像这样使用它:
"abc".match(stringToRegex("/a/g"))
//=> ["a"]
我建议您还为特殊标志添加单独的复选框或文本字段。这样很明显,用户不需要添加任何 //
。在替换的情况下,提供 两个 文本字段。这会让你的生活轻松很多。
为什么?因为否则有些用户会添加 //
,而其他用户则不会。有些会出现语法错误。然后,在您剥离 //
之后,您最终可能会得到一个语法上有效的正则表达式,这与用户的意图完全不同,从而导致奇怪的行为(从用户的角度来看)。
这是我处理自定义分隔符和无效标志的一个线性函数
函数 stringToRegex(s, m) { return (m = s.match(/^([\/~@;%#'])(.*?)\1([gimsuy]*)$/)) ?新 RegExp(m[2], m[3].split('').filter((i, p, s) => s.indexOf(i) === p).join('')) : 新正则表达式; } console.log(stringToRegex('/(foo)?\/bar/i')); console.log(stringToRegex('#(foo)?\/bar##gi')); //自定义分隔符 console.log(stringToRegex('#(foo)?\/bar##gig')); //过滤掉重复的标志 console.log(stringToRegex('/(foo)?\/bar')); // 视为字符串 console.log(stringToRegex('gig')); // 当作字符串处理
const stringToRegex = (s, m) => (m = s.match(/^([\/~@;%#'])(.*?)\1([gimsuy]*)$/)) ? new RegExp(m[2], m[3].split('').filter((i, p, s) => s.indexOf(i) === p).join('')) : new RegExp(s);
当字符串无效或不包含标志等时,这也将起作用:
function regExpFromString(q) { let flags = q.replace(/.*\/([gimuy]*)$/, '$1');如果(标志 === q)标志 = ''; let pattern = (flags ? q.replace(new RegExp('^/(.*?)/' + flags + '$'), '$1') : q);尝试{返回新的正则表达式(模式,标志); } 捕捉 (e) { 返回空值; } } console.log(regExpFromString('\\bword\\b')); console.log(regExpFromString('\/\\bword\\b\/gi'));
由于较早的答案,此块可以很好地用作将可配置字符串应用于 RegEx .. 以过滤文本的通用解决方案:
var permittedChars = '^a-z0-9 _,.?!@+<>';
permittedChars = '[' + permittedChars + ']';
var flags = 'gi';
var strFilterRegEx = new RegExp(permittedChars, flags);
log.debug ('strFilterRegEx: ' + strFilterRegEx);
strVal = strVal.replace(strFilterRegEx, '');
// this replaces hard code solt:
// strVal = strVal.replace(/[^a-z0-9 _,.?!@+]/ig, '');
您可以使用复选框请求标志,然后执行以下操作:
var userInput = formInput;
var flags = '';
if(formGlobalCheckboxChecked) flags += 'g';
if(formCaseICheckboxChecked) flags += 'i';
var reg = new RegExp(userInput, flags);
更安全,但不安全。 (不能访问任何其他上下文的 Function 版本会很好。)
const regexp = Function('return ' + string)()
我使用 eval
来解决这个问题。
例如:
function regex_exec() {
// Important! Like @Samuel Faure mentioned, Eval on user input is a crazy security risk, so before use this method, please take care of the security risk.
var regex = $("#regex").val();
// eval()
var patt = eval(userInput);
$("#result").val(patt.exec($("#textContent").val()));
}
不定期副业成功案例分享
var re = new RegExp("\\w+");
<input>
HTML 标记的变量中,则这些都不适用。var re = new RegExp("\"\\w+\"");
是使用 RegExp 构造函数的硬编码正则表达式的示例,并且双引号 is 的转义是必要的。我所说的变量中的字符串的意思是您可以执行var re = new RegExp(str);
并且str
可能包含双引号或反斜杠而没有问题。