Подтвердить что ты не робот

JavaScript RegExp для автоматического форматирования шаблона

Я видел много функций, которые форматируют телефон или номер (запятая и десятичная) в сообществе стека, как этот вопрос здесь и другие. Вот что я хочу:

Шаг 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 чисел в Date.

У меня есть текстовое поле:

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

И возможное место для запуска script как:

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


    //Some more steps here....

});

Но я не могу сделать дальше, потому что я новичок в RegExp. Здесь сценарий запуска. Кто-нибудь?

Дальнейшие заметки: я смог проверить, используя следующие функции, но то, что я хочу, автоматически создает шаблон:

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);
}
4b9b3361

Ответ 1

Это не так сложно, как вы думаете. Вы ищете JQuery Masked ввода и другие альтернативные библиотеки. Вот документация . Все что вам нужно:

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

и script:

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

Вот ссылка на демонстрационную ручку: http://codepen.io/anon/pen/gpRyBp

Для реализации проверки используйте эту библиотеку: https://github.com/RobinHerbots/jquery.inputmask

Ответ 2

Здесь необходимо разбить регулярное выражение в подвыражении, которое соответствует части строки, и предложить завершить на основе следующего символа в регулярном выражении. Я написал наивный парсер, который анализирует выражение и делит на атомное подвыражение.

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 вам нужно проверить список RegExp, сгенерированный parser, и если какой-либо из них соответствует вводу, используйте предложение.

EDIT:

Отредактировано generateSuggestion, чтобы соответствовать только полному выражению. Вот пример скрипта: http://jsfiddle.net/a7kkL6xu/6/

Если backspace игнорируется: http://jsfiddle.net/a7kkL6xu/7/

Ответ 3

Это можно сделать с помощью одного регулярного выражения.
Для этого требуется 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
и для проверки всей действительности, не должно быть никаких партиций и
группы 1 - 3 должны быть полными только для YYYY-MM-DD или 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)
 )

Ответ 4

Можно добавить символ, только если это единственный возможный выбор в этой точке. Примером может быть регулярное выражение для формата YYYY-MM-DD HH24:mm: -, : и (пробел). Вот соответствующее регулярное выражение (/, чтобы сделать его более читаемым, оно более строже, чем таковое в вопросе, некоторые незаконные даты все еще возможны, например, 31 февраля):

^[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]$

Входы с фиксированной длиной вы можете использовать решение @DineshDevkota​​strong > , чтобы добавить литералы и проверить весь текст с помощью регулярного выражения. Я считаю это самым простым и простым решением. Вы также можете записать год, месяц и день, чтобы проверить день математически. Также правила, такие как "дата не в будущем" или "максимум 100 лет назад", могут быть разрешены только в JS, а не только с регулярным выражением.

Единственные дополнительные шаблоны, которые приходят на ум, когда персонаж может быть добавлен автоматически:

  • A + после литерала, например. на A+ добавить A
  • Минимальные события в целом, например. на (?:foo){2,5} добавить foofoo не путать с [fo]{2,5}, где никакие символы не могут быть добавлены
  • Литералы после максимальной длины переменной части, например. на (?:foo){1,3}bar добавить bar после текста foofoofoo, прежде чем это невозможно.
  • Добавить остатки, например. foo|bar добавить ar при вводе b и oo при вводе f (также возможно в шаблоне, показанном в 3.), но это не будет работать для ^[a-z]+?(?:foo|bar)$, потому что мы не знаем когда пользователь планирует закончить текст, и он может стать действительно сложным (foo|flo|flu|food|fish только sh может быть добавлен после fi).

Как видно из 3. и 4., те дополнительные случаи, когда символы могут быть добавлены, очень ограничены, как только появляются части с переменной длиной. Вам придется анализировать регулярное выражение, разделять его в буквальном и регулярном выражении. Затем вам нужно проанализировать/проанализировать детали регулярных выражений, чтобы включить дополнительные случаи, упомянутые выше, в которые можно добавить символы. На самом деле не стоит того, чтобы спросить меня. (В вашем шаблоне tel нельзя добавить ни одного символа.)