Шаблон регулярного выражения соответствует только первым двум разам

1

Общий вопрос

Как вы предотвращаете соответствие регулярного выражения, если этот шаблон был сопоставлен 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".

Есть, вероятно, другие способы справиться с этой ситуацией (например, split и join), но для целей этого вопроса пусть придерживается ответа с правильным шаблоном регулярного выражения, если такой шаблон возможен. Происходят и другие вещи, которые сделали бы эту модель очень полезной - мне просто не повезло.


Для ясности этот шаблон будет запущен oninput в текстовом поле - совпадение должно работать для любой длины символов от 1 до 13:

"123456" -> "123-456"
"123456789" -> "123-456-789"
"1234567891011" -> 123-456-7891011"
  • 0
    @anubhava, который работает только для полной длины шаблона, а не для каждой ситуации. Я обновил ОП для ясности
  • 0
    Вы имеете в виду любую длину текста 1 - 15. Обрабатываете ли вы onkeypres, или на каждом вводе с клавиатуры, даже клавишу возврата или стрелки? Вы обрабатываете пасту ?
Показать ещё 3 комментария
Теги:

4 ответа

0
Лучший ответ

Использование регулярного выражения без дополнительного JS:

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

Начиная с начала строки, сопоставьте 3 цифры с необязательным "-" и, возможно, еще 3 цифры, а за ними следует последняя цифра в конце строки. Если это не соответствует, посмотрите, начинается ли строка с 3-х цифр, за которыми следует сразу конечная цифра в конце строки.

Получите немного фанки с группами захвата в строке замены, чтобы выполнить нужный формат.

3

Использовать обратные вызовы.

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

Решение, соответствующее вашим текущим потребностям, - это изменить шаблон и всегда идти полным путем:

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} имеют смысла.

  • 0
    Я думаю, что ваш второй пример будет продолжать добавлять дефисы к первым 3 цифрам.
  • 0
    @ NetMage - нет, так как шаблон соответствует необязательному дефису, если он следует группе из 3 цифр. Если это там, это будет "заменено".
Показать ещё 3 комментария
1

Вы можете использовать обратный вызов в рамках замены с некоторой логикой о том, как обрабатывать разделители. Это облегчит вам поведение, которое вы ожидаете.

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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню