正则表达式模式仅匹配前两次

时间:2017-06-26 18:20:12

标签: javascript regex

一般问题

如果该模式之前已匹配N次,如何阻止正则表达式匹配?

具体示例

我有一个13位数的记录标识符,用户将在文本字段中键入,例如“123-456-7891011”。

我试图封装的行为是在键入第4和第7位数字之前添加破折号。我有处理事件的所有javascript没有问题。

它始终是数字 - 我在此特定步骤之前处理它。

当我每次输入第n + 4位数字时,我能够正确地使用正则表达式来插入短划线。我需要的是它在第二个“ - ”

之后的任何时候都不要这样做

到目前为止,我在事件处理程序(oninput)中最接近的是:

var addDash = /([^\-\d{3}]*\d{3})(\d+)/;
this.value = this.value.replace(addDash, "$1-$2");

例如,输入“1234567891011”会产生“123-456-789-101-1”,其中我想要的是“123-456-7891011”。

可能其他方式可以处理这种情况(例如splitjoin)但是出于这个问题的目的,让我们坚持回答正确的正则表达式模式,如果这样的模式是可能的。还有其他事情会使这种模式变得非常有用 - 我只是没有运气了。

为了清晰,此模式将在文本字段上运行oninput - 匹配应适用于1到13之间的任意字符长度:

"123456" -> "123-456"
"123456789" -> "123-456-789"
"1234567891011" -> 123-456-7891011"

4 个答案:

答案 0 :(得分:3)

使用callbacks

  

您可以将函数指定为第二个参数。在这种情况下,将在执行匹配后调用该函数。函数的结果(返回值)将用作替换字符串。

针对您当前需求的解决方案是改变模式并始终进行完全匹配:

this.value = this.value.replace(/^(\d{3})-?(\d{3})?-?(\d*)$/, function (m, a, b, c) {
    return b ? a + "-" + b + "-" + c : a + "-" + c;
});

完成工作。

如果您想要更通用的解决方案,可以使用计数器变量:

var count = 0;
this.value = this.value.replace(/(\d{3})-?/g, function (m, a) {
    return ++count <= 2 ? a + "-" : m;
});

这个模式使用的模式不太适合您的需求,但它可以演示如何推广到真正需要限制替换次数的不同情况。

顺便说一句,你有一种语法误解:[^\-\d{3}] 意味着你的想法。它将匹配单个字符,该字符不是数字或其中任何一个:-{}[ ... ]括号内的所有内容都定义了字符类,因此{n}等量词在那里毫无意义。

答案 1 :(得分:1)

您可以在替换中使用回调,以及如何处理分隔符的一些逻辑。这样可以更轻松地获得您期望的行为。

&#13;
&#13;
var values = ['12', '123', '123-4', '123-45', '123-456', '123-456-7', '123-456-7891011'];
var addDash = /^(\d{3})-?(\d?\d?\d?)-?(\d*)/;
values.forEach(function(value) {
  value = value.replace(addDash, function(match, capture1, capture2, capture3) {
    var secondDelimiter = capture2.length == 3 ? '-' : '';
    return capture1 + '-' + capture2 + secondDelimiter + capture3;
  });

})
console.log(values)
&#13;
&#13;
&#13;

答案 2 :(得分:0)

使用正则表达式而无需额外的JS:

var addDash = /^((\d{3}\-?)(\d{3}\-?)?)(\d)$|^(\d{3})(\d)$/;
this.value = this.value.replace(addDash, "$1$5-$4$6");

从字符串的开头开始,使用可选的&#34; - &#34;以及可选的3个数字匹配3位数字,然后紧跟字符串末尾的最后一位数字。如果不匹配,请查看字符串是否以3位数字开头,后面紧跟字符串末尾的最后一位数字。

使用替换字符串中的捕获组获得一点时髦,以实现所需的格式。

答案 3 :(得分:-3)

$(function() {
    var txt='1232';
    var addDash = /^(\d{3})-?(\d?\d?\d?)-?(\d*)/;
    $("#test").html(txt.replace(addDash, function(match, capture1, capture2, capture3) {
        var firstDelimiter = (capture1.length == 3 && capture2.length > 0) ? '-' : '';
        var secondDelimiter = (capture2.length == 3 && capture3.length > 0) ? '-' : '';
        return capture1 + firstDelimiter + capture2 + secondDelimiter + capture3;
    }));
})