这里有一个简单的概念证明,可以在jsFiddle中看到。你只需要逆向循环所提出的正则表达式,并寻找最长的子匹配。
注意:这个方法已知存在一个问题,就是它不能很好地处理组。例如,它会说foo bar b
根本不匹配foo( bar)+
,然而它应该说仍然有希望。这个问题可以通过对下面这行代码更加创造性地进行修复来解决:
temp_re = new RegExp(regex_part+'$'); // make sure this partial match ends in a piece that could still match the entire regex
基本上,您需要解析部分正则表达式以查看它是否以组结尾,然后递归地检查该结尾组的部分匹配。这相当复杂,因此我不会在我的演示中涉及它。
JavaScript(仅用于演示目的使用jQuery):
var strings = {
matches: "Matches!",
stillhope: "There's still hope...",
mismatch: "Does not match",
empty: "No text yet"
};
function PartialRegexMonitor(regex, input_id) {
var self = this;
this.relen = regex.length;
$('body').on('keyup', '#'+input_id, function() {
self.update_test_results(regex, input_id);
});
}
PartialRegexMonitor.prototype.update_test_results = function(regex, input_id) {
var input = $('#'+input_id).val(),
matches = find_partial_matches(regex, input),
span = $('#'+input_id).siblings('.results');
span.removeClass('match');
span.removeClass('stillhope');
span.removeClass('mismatch');
span.removeClass('empty');
span.addClass(matches.type)
.html(strings[matches.type]);
}
function partial_match_tester(regex_part, str) {
var matched = false;
try {
var re = new RegExp(regex_part, 'g'),
matches = str.match(re),
match_count = matches.length,
temp_re;
for(var i = 0; i < match_count; i++) {
temp_re = new RegExp(regex_part+'$');
matched = temp_re.test(str);
if(matched) break;
}
}
catch(e) {
}
return matched;
}
function find_partial_matches(regex, str) {
var relen = regex.length,
matched = false,
matches = {type: 'mismatch',
len: 0},
regex_part = '';
if(str.length == 0) {
matches.type = 'empty';
return matches;
}
for(var i=relen; i>=1; i--) {
if(i==1 && str[0] == '^') {
continue;
}
regex_part = regex.substr(0,i);
regex_part = regex_part.replace(/\{(\d)\}$/g, '{0,$1}');
matched = partial_match_tester(regex_part, str);
if(matched) {
matches.type = (i==relen ? 'matches' : 'stillhope');
console.log(matches.type + ": "+regex.substr(0,i)+" "+str);
matches.len = i;
break;
}
}
return matches;
}
$(function() {
new PartialRegexMonitor('foo bar', 'input_0');
new PartialRegexMonitor('^foo bar$', 'input_1');
new PartialRegexMonitor('^fo+(\\s*b\\S[rz])+$', 'input_2');
new PartialRegexMonitor('^\\d{3}-\\d{3}-\\d{4}$', 'input_3');
});
演示用的HTML代码:
<p>
Test against <span class="regex">foo bar</span>:<br/>
<input type="text" id="input_0" />
<span class="results empty">No text yet</span>
</p>
<p>
Test against <span class="regex">^foo bar$</span>:<br/>
<input type="text" id="input_1" />
<span class="results empty">No text yet</span>
</p>
<p>
Test against <span class="regex">^fo+(\s*b\S[rz])+$</span> (e.g., "foo bar", "foo baz", "foo bar baz"):<br/>
<input type="text" id="input_2" />
<span class="results empty">No text yet</span>
</p>
<p>
Test against <span class="regex">^\d-\d-\d$</span>:<br/>
<input type="text" id="input_3" />
<span class="results empty">No text yet</span>
</p>
演示用的CSS
.empty {
background-color: #eeeeee;
}
.matches {
background-color: #ccffcc;
font-weight: bold;
}
.stillhope {
background-color: #ccffff;
}
.mismatch {
background-color: #ffcccc;
font-weight: bold;
}
.regex {
border-top:1px solid #999;
border-bottom:1px solid #999;
font-family: Courier New, monospace;
background-color: #eee;
color: #666;
}
演示的示例截图
![enter image description here](https://istack.dev59.com/AM1VJ.webp)
^o(?:n(?:e(?: (?:(?:two)*(?:t(?:w(?:o(?: (?:t(?:h(?:r(?:e(?:e.*?)?)?)?)?)?)?)?)?)?)?)?)?)?$
,以检查文本是否有前途。如果你的表达式不太复杂,我相信可以自动从主表达式派生有前途的正则表达式。 - Ulugbek Umirov