JavaScript RegExp自动格式化Pattern

时间:2015-06-07 21:55:35

标签: javascript regex

我已经看到很多函数在stackflow社区中格式化电话或数字(逗号和小数),就像这个问题here和其他人一样。这就是我想要的:

第1步:为图书馆维护这样的图片:

var library = {
    fullDate : {
        pattern : /^[0-9]{4}-[0-9]{1,2}-[0-9]{1,2}$/,
        error : "Invalid Date format. Use YYYY-MM-DD format."
    },
    fullDateTime : {
        pattern : /^[0-9]{4}-[0-9]{1,2}-[0-9]{1,2} [0-9]{1,2}:[0-9]{1,2}$/,
        error : "Invalid DateTime format. Use YYYY-MM-DD HH:MM (24-hour) format."
    },
    tel : {
        pattern : /^\(?([0-9]{3})\)?[-. ]?([0-9]{3})[-. ]?([0-9]{4})$/,
        error : "Invalid Telephone format."
    }
};

第2步:在键入时自动添加字符。例如,请在日期中的4个数字后添加-

我有一个文字字段说:

<input type="text" data-validate="fullDate" placeholder="YYYY-MM-DD"/>

启动脚本的可能位置为:

$('body').on('keyup','input',function(){
   var validate = $(this).data('validate');
   var pattern = library[validate].pattern;


    //Some more steps here....

});

但是,我不能再进一步了,因为我是RegExp的新手。这是 startup fiddle 。任何人吗?

进一步说明:我已经能够使用以下功能进行验证,但我想要的是自动制作模式:

function validate(libraryItem, subject){
    var item = library[libraryItem];
    if(item !== undefined){
        var pattern = item.pattern;
        if(validatePattern(pattern, subject)){
            return true;
        } else {
            return item.error;
        }
    }
    return false;
}


function validatePattern(pattern, subject){
    return pattern.test(subject);
}

4 个答案:

答案 0 :(得分:6)

它并不像你想象的那么复杂。您正在寻找的是JQuery Masked输入和其他替代库。这是documentation。您所需要的只是:

 <input id="date" type="text" placeholder="YYYY-MM-DD"/>

和脚本:

 $("#date").mask("9999-99-99",{placeholder:"YYYY-MM-DD"});

这是演示笔链接: http://codepen.io/anon/pen/gpRyBp

要实现验证,请使用此库: https://github.com/RobinHerbots/jquery.inputmask

答案 1 :(得分:2)

这里需要的是分解子表达式中的正则表达式,该表达式匹配字符串的一部分,并根据正则表达式中的下一个字符建议完成。 我写了一个天真的Parser,它解析表达式并分为原子子表达式。

var parser = function(input) {
    var tokenStack = [];
    var suggestions = [];
    var suggestion;
    var lookAhead;

    if (input[0] === '/')
        input = input.slice(1, input.length - 1);

    var i;
    for (i = 0; i < input.length - 1; i++) {
        lookAhead = input[i + 1];
        switch (input[i]) {
        case '(':
            tokenStack.push('(');
            break;
        case '[':
            tokenStack.push('[');
            break;
        case ')':
            if (tokenStack[tokenStack.length - 1] === '(') {
                tokenStack.pop();
                if (tokenStack.length === 0) {
                    suggestion = generateSuggestion(input, i);
                    if (suggestion !== null)
                        suggestions.push(suggestion);
                }
            }
            else
                throw 'bracket mismatch';
            break;
        case ']':
            if (lookAhead === '{') {
                while (input[i] !== '}')
                    i++;
            }
            if (tokenStack[tokenStack.length - 1] === '[') {
                tokenStack.pop();
                if (tokenStack.length === 0) {
                    suggestion = generateSuggestion(input, i);
                    if (suggestion !== null)
                        suggestions.push(suggestion);
                }
            }
            else
                throw 'bracket mismatch';
            break;
        default:
            if (tokenStack.length === 0) {
                suggestion = generateSuggestion(input, i);
                if (suggestion !== null)
                    suggestions.push(suggestion);
            }
            break;
        }
    }
    return suggestions;
}

var generateSuggestion = function(input, index) {
    if (input[index].match(/[a-zA-Z\-\ \.:]/) !== null)
        return {
            'regex': input.slice(0, index) + '$',
            'suggestion': input[index]
        };
    else
        return null;
}

以下是parser()

的示例输入和输出
parser('/^[0-9]{4}-[0-9]{1,2}-[0-9]{1,2}$/');
// output:
[ { regex: '^[0-9]{4}$', suggestion: '-' },
  { regex: '^[0-9]{4}-[0-9]{1,2}$', suggestion: '-' } ]

因此,在每个keyup上,您需要检查由parser生成的RegExp列表,如果其中任何一个与输入匹配,则使用该建议。

编辑:

编辑generateSuggestion以仅匹配完整表达式。 以下是样本小提琴:http://jsfiddle.net/a7kkL6xu/6/

忽略退格:http://jsfiddle.net/a7kkL6xu/7/

答案 2 :(得分:2)

这可以使用单个正则表达式完成 这要求MM:DD和HH:MM为2位,YYYY为4位数 完全有效的输入,但匹配所有部分。

可以允许所提到的2位有效数字的单个数字有效性 但这样做会在- - [ ] :表单上提出过早的建议 如果您不想注入建议,那么1或2位数就可以了。

JavaScript不允许使用lookbehind断言,因此部分字段表达式为 低于各自组中的有效字段表达式。

基本上,每次按键事件都会输入重写 您所做的就是匹配事件处理程序中的当前输入。

如果没有建议,您只需使用整个匹配(组0)写入输入。

匹配(组0)仅包含有效的部分或完全匹配。

有效完成的字段捕获组为1到5
[年,月,日,小时,分钟]

不完整的字段捕获是第6到第10组 [分钟,小时,日,月,年]

这是逻辑:

// Note 1 - can handle control chars by just returning.
// Note 2 - can avoid rewrite by keeping a global of last good,
//          then return if current == last.

if ( last char of group 0 is a dash '-' or space ' ' or colon ':' 
     or any of groups 6 - 10 matched
     or group 5 matched )
   set input equal to the group 0 string;  

else if ( group 4 matched )  // Hours
   set input equal to  group 0 string + ':';  

else if ( group 3 matched )  // Day
   set input equal to group 0 string + ' ';  

else if ( group 1 or 2 matched )  // Year or Month
   set input equal to  group 0 string + '-';   

else   // Here, effectively strips bad chars from input box
       // before they are displayed.
   set input equal to  group 0 string;   

请注意,如果某个群组没有匹配,则其值 NULL
并检查整个有效性,应该没有部分和 对于YYYY-MM-DD,组1 - 3必须完整,或者使用可选的
组,1 - 5组必须完成 时间HH:MM

最后的注意事项:这是一个解析器,实际上是外观的测试用例,即。闪烁,实时输入重写。
如果进展顺利,处理程序中的逻辑可以包括基于月份的日期验证(和重写) 此外,前提可以扩展到任何类型的输入,任何类型的形式和 形式分隔符组合等。
如果它有效,您可以构建一个库。

 # /^(?:(19\d{2}|20[0-1]\d|202[0-5])(?:-(?:(0[1-9]|1[0-2])(?:-(?:(0[1-9]|[1-2]\d|3[0-1])(?:[ ](?:(0\d|1\d|2[0-3])(?::(?:(0\d|[1-5][0-9])|([0-5]))?)?|([0-2]))?)?|([0-3]))?)?|([01]))?)?|(19\d?|20[0-2]?|[12]))/


 ^                             # BOL 
 (?:
      (                             # (1 start), Year 1900 - 2025
           19 \d{2} 
        |  20 [0-1] \d 
        |  202 [0-5] 
      )                             # (1 end)
      (?:
           -                             # -
           (?:
                (                             # (2 start), Month    00 - 12
                     0 [1-9] 
                  |  1 [0-2] 
                )                             # (2 end)
                (?:
                     -                             # -
                     (?:
                          (                             # (3 start), Day   00 - 31
                               0 [1-9] 
                            |  [1-2] \d 
                            |  3 [0-1] 
                          )                             # (3 end)
                          (?:
                               [ ]                           # space
                               (?:
                                    (                             # (4 start), Hour  00 - 23
                                         0 \d 
                                      |  1 \d 
                                      |  2 [0-3] 
                                    )                             # (4 end)
                                    (?:
                                         :                             # :
                                         (?:
                                              (                             # (5 start), Minutes  00 - 59
                                                   0 \d 
                                                |  [1-5] [0-9]                                             
                                              )                             # (5 end)
                                           |  
                                              ( [0-5] )                     # (6)
                                         )?
                                    )?
                                 |  
                                    ( [0-2] )                     # (7)
                               )?
                          )?
                       |  
                          ( [0-3] )                     # (8)
                     )?
                )?
             |  
                ( [01] )                      # (9)

           )?
      )?
   |  
      (                             # (10 start)
           19 \d? 
        |  
           20 [0-2]? 
        |  
           [12] 
      )                             # (10 end)
 )

答案 3 :(得分:1)

此时只能添加一个字符,这是唯一可能的选择。一个示例是has_many格式的正则表达式:config/database.yml ,可以添加YYYY-MM-DD HH24:mm-(空格)。以下是相应的正则表达式(:,使其更易读,它比问题中的更严格,一些非法日期仍然可能像2月31日那样):

对于固定长度输入,您可以使用@ DineshDevkota解决方案添加文字并使用正则表达式验证整个文本。我认为这是最干净,最简单的解决方案。您还可以捕获年,月和日以数学方式验证日期。同样的规则如&#34;日期不会在未来&#34;或者&#34;最大过去100年&#34;只能在JS中使用,而不仅仅是正则表达式。

可以自动添加角色的唯一额外模式:

  1. 字面后的/,例如在^[0-9]{4}-(?:0[1-9]|1[0-2])-(?:0[1-9]|[12][0-9]|3[01]) (?:[01][0-9]|2[0-3]):[0-5][0-9]$ 上添加+
  2. 一般情况下最少发生,例如在A+上添加A,不要与无法添加字符的(?:foo){2,5}混淆
  3. 在可变部分的最大长度之后的文字,例如foofoo在文字[fo]{2,5}之后添加(?:foo){1,3}bar,然后才能进行。{/ li>
  4. 添加余数,例如键入barfoofoofoo {}添加foo|bar,键入ar时添加b(也可以在3中显示的模式中添加),但这会赢得&#39}。适用于oo,因为我们不知道用户何时计划结束文本并且可能会变得非常复杂(f ^[a-z]+?(?:foo|bar)$可以在{{1}之后添加})。
  5. 如在3.和4中所见。只要有可变长度的部分,那些可以添加字符的附加情况的使用非常有限。您必须解析正则表达式,将其拆分为文字和正则表达式部分。然后你必须解析/分析正则表达式部分,以包含上面提到的可以添加字符的其他情况。如果你问我,真的不值得麻烦。 (您的电话模式中不能添加单个字符。)