Ограничение входных данных

Я новичок в регулярных выражениях. Я читал о регулярном выражении последние пару часов, чтобы понять, как использовать регулярное выражение * для достижения следующего, но без особого успеха. У меня заболел мозг. Отсюда и этот призыв о помощи. Ниже приведены ограничения, которые я хочу применить к полю ввода данных. Какое регулярное выражение мне следует использовать?

  1. Первый и последний символы должны быть буквенно-цифровыми, "." (т. е. точка) или "_" (т. е. подчеркивание)
  2. Символы между первым и последним символами могут быть буквенно-цифровыми, "." (т. е. точка), "_" (т. е. подчеркивание) или "-" (т. е. дефис)
  3. Символы "." (т. е. точка) и "-" (т. е. дефис) не могут появляться последовательно.
  4. Во вводимых данных должен быть хотя бы один буквенно-цифровой символ.

Некоторые допустимые входные данные:

.abc_
__abc.d-e.
.__a.
.a__b.
_a-b.
abc
a___.

Спасибо и привет,

~ Вилка

  • Я использую стороннюю библиотеку, которая внутренне использует boost-regex для анализа выражения.

person user1937634    schedule 04.06.2013    source источник
comment
Как сейчас звучит, это похоже на код Морзе o_o Вы можете предоставить образец?   -  person HamZa    schedule 04.06.2013
comment
@HamZa Готово! Добавлено несколько примеров ввода текста.   -  person user1937634    schedule 04.06.2013
comment
Я не уверен, что это возможно с регулярным выражением. По крайней мере, не легко.   -  person Sean Bright    schedule 04.06.2013
comment
Может ли строка иметь длину 1 или 2? (например, "A" или "AB" - оба из которых соответствуют всем вашим требованиям?)   -  person ridgerunner    schedule 04.06.2013


Ответы (3)


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

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

^[a-zA-Z0-9\._](?:[a-zA-Z0-9_]*(?:\.(?!\.))*(?:-(?!-))*[a-zA-Z0-9_]*)*[a-zA-Z0-9\._]$

Кто-то может прийти с более красивым отформатированным, но, похоже, он работает http://www.regex101.com/ для всего, на чем я его тестировал.

person ydaetskcoR    schedule 04.06.2013
comment
Я сделал вариацию вашего регулярного выражения, оно обрабатывает правило 3 для первого и последнего символов, а также правило 4 (в порядке положительного просмотра). ^(?=.*[[:alnum:]])[[:alnum:]_.](?:[[:alnum:]_]|(?<!\.)\.|-(?!-))*(?:[[:alnum:]_]|(?<!\.)\.)$ - person Hasturkun; 04.06.2013
comment
Приведенное выше регулярное выражение работает нормально, когда есть совпадение, но может легко перейти в катастрофический возврат когда не совпадает. т.е. он имеет классическую форму: ^(a*a*)*$, и при применении к строке "aaaaaaaaaab" требует много, многих итераций для объявления несоответствия. - person ridgerunner; 05.06.2013

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

Для ваших условий 1 и 2 текст должен соответствовать следующему (с учетом того, что текст может состоять только из одного символа):

 ^([a-z0-9._]|[a-z0-9._][a-z0-9_.-]*[a-z0-9._])$  

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

 .*[.-][.-].*
 .*(.-|-.).*
 .*(\.\.|--).*

Для вашего условия 4 текст должен соответствовать следующему:

 .*[a-z0-9].*  

Я не позволил здесь использовать символы верхнего регистра. При необходимости добавьте их в шаблоны символов.

person mc0e    schedule 04.06.2013

Интересная проблема. Можно решить с помощью нетривиального регулярного выражения. Вот он в синтаксисе Java (который требует, чтобы регулярное выражение было заключено в строку.)

Pattern re_valid = Pattern.compile(
    "    # Regex to validate special word requirements.                                   \n" +
    "    ^                             # Anchor to start of string. And...                \n" +
    "    (?=[A-Za-z0-9._])             # First char is alphanum, dot or underscore. And...\n" +
    "    (?=.*[A-Za-z0-9._]$)          # Last char is alphanum, dot or underscore. And... \n" +
    "    (?=[^A-Za-z0-9]*[A-Za-z0-9])  # Contains at least one alphanum.                  \n" +
    "    (?:                           # Group two possible content formats.              \n" +
    "      [A-Za-z0-9_]+               # Case 1: Begins with one or more non-[-.].        \n" +
    "      (?:                         # Zero or more [-.] separated parts.               \n" +
    "        [-.]                      # Each part separated by one [-.],                 \n" +
    "        [A-Za-z0-9_]+             # followed by one or more non-[-.].                \n" +
    "      )*                          # Zero or more [-.] separated parts.               \n" +
    "      [.]?                        # May end with one [-.].                           \n" +
    "    | [.]                         # Or Case 2: Begins with hyphen or dot.            \n" +
    "      (?:                         # Zero or more [-.] separated parts.               \n" +
    "        [A-Za-z0-9_]+             # One or more non-[-.],                            \n" +
    "        [-.]                      # followed by one [-.].                            \n" +
    "      )*                          # Zero or more [-.] separated parts.               \n" +
    "      [A-Za-z0-9_]*               # May end with zero or more non-[-.].              \n" +
    "    )                             # End group of two content alternatives.           \n" +
    "    $                             # Anchor to end of string.                         ", 
    Pattern.COMMENTS);
person ridgerunner    schedule 04.06.2013
comment
Для дополнительной похвалы напишите его, чтобы он обрабатывал ввод от начала до конца без возврата. - person mc0e; 05.06.2013