Проверьте, является ли строка префиксом Javascript RegExp

В Javascript я определил регулярное выражение, и теперь пользователь вводит строку. Я хочу сказать ему, может ли его строка соответствовать RegExp, если он продолжит печатать, или он уже ошибается. Например:

var re = /a*b/;

"a".isPrefixOf( re ); // true
"x".isPrefixOf( re ); // false

Как могла бы выглядеть реализация isPrefixOf?

Обновлять: Спасибо за ваши ответы, обеспечение защиты от префиксов регулярных выражений, как предлагает Брэд, кажется хорошим обходным путем. Но я все еще пытаюсь найти общее решение.

Может быть, так: мы создаем новое регулярное выражение с вводом пользователя, за которым следует .*. Это регулярное выражение описывает все слова, которые пользователь может вводить. Если пересечение этого созданного регулярного выражения и исходного регулярного выражения пусто, значит, пользователь уже находится на неправильном пути. Если нет, то он в порядке. Например:

var re = /a*b/;
var sInput = "a";
var reInput = new RegExp( sInput + ".*" );

reIntersection = re.intersect( reInput );
reIntersection.isEmpty(); // false

intersect() возвращает новое регулярное выражение, которое принимает только слово, которое будут принимать как re, так и reInput. Функция еще не существует, но мы можем реализовать ее с опережением:

RegExp.prototype.intersect = function( pattern2 ) { 
    return new RegExp( '(?=' + this.source  + ')' + pattern2.source );
}

Что остается открытым, так это функция isEmpty(). Как мы могли проверить, соответствует ли регулярное выражение Javascript какому-либо слову или оно пустое?

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
14
0
5 733
5

Ответы 5

Сначала вы определяете свое регулярное выражение как: var re = new RegExp (/ ^ (здесь regexp) $ /);

в событии onKeypress вы проверяете регулярное выражение следующим образом:

text.match (regexp) - где текст - это введенная строка.

Это понятно?

Вам следует прочитать вопрос более внимательно. Не спрашивает, как вызвать совпадение. Спрашивает, как написать сопоставитель.

user51568 06.01.2009 17:03

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

"a".isPrefixOf( re ); // true

никогда не будет совпадать, так как он должен иметь следующий символ «b» (вы можете изменить регулярное выражение). Например, этот код будет проверять любую строку, соответствующую этому формату:

a-n(n)-b

Вот код, сохраните его как страницу и загрузите в свой браузер:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns = "http://www.w3.org/1999/xhtml" xml:lang = "en" lang = "it">
<body>
    <input type = "text" size = "20" id = "txtData" onkeyup = "showResult()" />
    <div id = "dvResult" />
</body>
</html>
<script type = "text/javascript">
//<![CDATA[

    theRegExp = /^a\-\d{1,2}\-b$/;

    function isPrefixOf( aText, aRegExp )
    {
        return aRegExp.test( aText );
    }

    function showResult()
    {
        res = document.getElementById( "dvResult" );
        res.innerHTML = isPrefixOf( document.getElementById( "txtData" ).value, theRegExp ) ? "Correct" : "Bad input";
    }

//]]>
</script>

Вам следует прочитать вопрос более внимательно. Не спрашивает, как вызвать совпадение. Спрашивает, как написать сопоставитель.

user51568 06.01.2009 17:04

Вот почему я выделил это примечание жирным шрифтом!

Manuel 06.01.2009 18:12

Хотя вопрос можно было бы сформулировать лучше, я думаю, что его нетрудно понять. Какой голос вы хотите, чтобы я удалил?

user51568 06.01.2009 21:11

Очень интересный вопрос. В моем быстром поиске я не нашел ничего предопределенного (даже в Perl), которое решало бы эту проблему.

Обновлено: Ой, похоже, в Java есть что-то похожее, называемое hitEnd () - см. Ответ Алана М. HitEnd () сообщает, что результат match () (истинный или ложный) может быть изменен дополнительным вводом. В книге «Освоение регулярных выражений» говорится, что это не очень надежно (не знаю, почему, страница 392 недоступна в книгах Google).

В зависимости от того, какие функции регулярных выражений вы используете, быстрый взлом, например, написание каких-то префиксов вашего регулярного выражения:

например для a + a * b + c ваши префиксы будут такими:

a+
a+a*
a+a*b+
a+a*b+c

и попробуйте сопоставить любой из них с вашей строкой, может сработать. Этот быстрый прием затруднен, если вы используете оператор выбора, если вы используете оператор диапазона {n, m} или обратные ссылки.

При этом я думаю, что хорошее решение - немного изменить алгоритм сопоставления.

Обычно используемый алгоритм сопоставления представляет собой алгоритм отслеживания с возвратом (который хорошо работает на практике, даже если поведение в худшем случае является экспоненциальным). Этот алгоритм успешно завершается всякий раз, когда он достигает конца регулярного выражения (даже если не вся строка была использована). Что вам нужно сделать, так это изменить условие завершения так, чтобы оно также успешно завершалось, когда оно потребляет весь ввод.

При этом вам, вероятно, придется реализовать алгоритм на JavaScript. Надеюсь, это станет частью таких библиотек, как JQuery.

Для получения дополнительных ссылок и теории алгоритма ознакомьтесь с этой статьей:

http://swtch.com/~rsc/regexp/regexp1.html

(даже если он опровергает алгоритм обратного отслеживания и предлагает алгоритм на основе FA (но FA не может обрабатывать обратные ссылки)).

Я думаю, что лучше всего сделать ваше Regex устойчивым к префиксу. Для приведенного вами примера, /a*b/, я думаю, вы могли бы использовать /a*b?/.test(userinput). Для более сложных шаблонов это может стать все труднее, но я все же думаю, что это можно сделать, вложив каждое подвыражение в серию необязательных квантификаторов (?). Например:

/a*bcd*e/

Регулярное выражение префикса может быть:

/a*(b(c(d*e?)?)?)?/

Это немного беспорядочно, но, я думаю, решит вашу проблему довольно хорошо.

Это отличная идея (вы получаете голос "за"), но я думаю, что она быстро разрушается для более сложных моделей. Как создать префиксное регулярное выражение для следующего шаблона? / a (bc | BC) d /

Prestaul 06.01.2009 23:48

Кажется, что люди поровну интерпретируют этот вопрос, поэтому я продемонстрирую эту концепцию на примере Java.

import java.util.regex.*;

public class Test
{

  public static void main(String[] args) throws Exception
  {
    tryMatch("^a*b+$", "a", "ab", "abc");
  }

  public static void tryMatch(String regex, String... targets)
  {
    Pattern p = Pattern.compile(regex);
    Matcher m = p.matcher("");
    System.out.printf("%nregex: %s%n", regex);
    System.out.printf("target | matches() | hitEnd()%n");
    for (String str : targets)
    {
      m.reset(str);
      System.out.printf("%-6s | %-9B | %-9B%n",
          str, m.matches(), m.hitEnd());
    }
  }
}

выход:

regex: ^a*b+$
target | matches() | hitEnd()
a      | FALSE     | TRUE
ab     | TRUE      | TRUE
abc    | FALSE     | FALSE

Целевая строка «a» не совпадает, потому что для регулярного выражения требуется хотя бы один b, но это может быть префикс успешного совпадения, поэтому hitEnd() возвращает true. Строка «ab» содержит все, что требуется для совпадения, но она также будет соответствовать, если мы добавим больше b в конец, поэтому hitEnd() по-прежнему возвращает true. С «abc» попытка сопоставления не удалась до того, как достигнет конца целевой строки, поэтому регулярное выражение не может сопоставить ни одну строку, которая начинается с «abc».

Насколько мне известно, в Javascript нет ничего похожего на метод Java hitEnd(), но его можно подделать. Если кто знает как, то это будет тот самый вопиющий задира, Стивен Левитан.

Другие вопросы по теме