Как написать регулярное выражение, которое позволяет неповторяющиеся подчеркивания - PullRequest
1 голос
/ 26 марта 2019

Я работаю над домашним заданием, чтобы использовать Flex для создания лексера.Последнее требование, которое я должен выполнить:

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

Данное регулярное выражение [A-Za-z][A-Za-z0-9]*.Распознать подчеркивание было легко, я просто добавил его во вторую группу, например [A-Za-z][A-Za-z0-9_]*.Таким образом, регулярное выражение не соответствует ни одной строке с начальным подчеркиванием.

Проводя тщательную проверку, чтобы убедиться, что я не публикую то, что мне не нужно, я создал это регулярное выражение, которое, кажется, работает [A-Za-z]([A-Za-z0-9][_]?[A-Za-z0-9])*.При этом начинается поиск буквы в начале, затем повторяющегося шаблона или буквенно-цифрового символа, возможного подчеркивания и буквенно-цифрового символа.Хотя это работает, я не думаю, что это то, что ожидается, и надеялся получить какой-нибудь совет относительно лучших способов

Я тестировал, используя следующие строки (предоставленные инструктором):

name_1
name__2
_name3
name4_

Ответы [ 4 ]

3 голосов
/ 26 марта 2019

В вашем [A-Za-z]([A-Za-z0-9][_]?[A-Za-z0-9])* первое [A-Za-z0-9] может / должно быть опущено (например, идентификаторы из одной буквы), что приводит к [A-Za-z]([_]?[A-Za-z0-9])*. Похоже, это именно то, что было задано, и это хорошее упражнение для изучения эффектов объединения необязательных элементов при повторении в регулярном выражении.

1 голос
/ 26 марта 2019

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

[A-Za-z][A-Za-z0-9]*(_[A-Za-z0-9]+)*

Я только что добавил (_[A-Za-z0-9]+)* часть, которая будет позволять одиночному подчеркиванию, за которым следует хотя бы один буквенно-цифровой символ, целое его ноль или более раз, чтобы сохранить только подчеркивание необязательным.

Теперь вам придется позаботиться о других аспектах, так как я не знаком с flex.

0 голосов
/ 26 марта 2019

Чтобы делать то, что вы хотите, вы должны помнить несколько вещей:

  • Начните с буквенно-цифрового значения (^)
  • Конец буквенно-цифровым значением ($)
  • Необязательное подчеркивание (_?)
  • Возможно несколько символов подчеркивания, за которыми всегда следует буквенно-цифровой код ()*

Пример

    ^[A-Za-z]+(_?[A-Za-z0-9]+)*$

Тест здесь: https://regex101.com/r/RORy6P/5

Вы можете оставить якоря подальше, если вам нужно.

0 голосов
/ 26 марта 2019

Проходя через это, давайте начнем с этого:

^    [A-Z][A-Z\d_]+    $

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

(?:(?!__).)+

Когда мы вставляем это в наше выражение, мы получаем что-то вроде этого, что позволяет любому символу, так долготак как это не новая строка или двойное подчеркивание:

^    [A-Z]    (?:(?!__).)+    $

Итак, мы можем заменить точку классом символов, который мы определили в начале:

^    [A-Z]    (?:(?!__)[A-Z\d_])+    $

Здесьдемонстрация

Редактировать: только что понял, что вы не можете иметь подчеркивание в конце либо.С помощью заголовков вы можете связать их в цепочку.

^[A-Z]    (?:    (?!__)    (?!_$)    [A-Z\d_]    )+$

Здесь я добавил один отрицательный прогноз для двойного подчеркивания и еще один для подчеркивания в конце.

Вот демонстрация

...