Форум программистов, компьютерный форум, киберфорум
Delphi для начинающих
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.75/48: Рейтинг темы: голосов - 48, средняя оценка - 4.75
1 / 1 / 0
Регистрация: 09.11.2013
Сообщений: 7
1

Регулярные выражения в Delphi — тонкости синтаксиса (модуль RegularExpressions)

09.11.2013, 10:59. Показов 8671. Ответов 5
Метки нет (Все метки)

Здравствуйте, уважаемые коллеги!

Обстоятельства: Win7, Delphi XE5 + стандартный ("родной") модуль RegularExpressions.

Задача: средствами регулярных выражений произвести проверку вводимого пользователем пароля и определить его "валидность". Валидным должен считаться пароль,
содержащий:
• строчные и прописные латинские буквы;
• цифры;
• любой из символов: `~!@#$%^&*()_+-={}|[]\:";'<>?,./;
и не содержащий:
• любые другие символы, в т.ч., пробелы.
Пароль должен иметь длину от 0 до 128 символов (допускается отсутствие пароля).

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

Само выражение выглядит так:
^[a-zA-Z0-9`~!@#\$%\^&\*\(\)_\+-=\{\}\|\[\]\\:";'\<\>\?,\./]{0,128}$
(экранированы символы: $ ^ * ( ) + { } | [ ] \ < > ? .)

В Дельфи для того, чтобы строковая константа нормально обрабатывалась, дополнительно экранирован символ «одинарная кавычка»: '

Таким образом, строковая константа, содержащая соответствующее выражение в Delphi выглядит так:
'^[a-zA-Z0-9`~!@#\$%\^&\*\(\)_\+-=\{\}\|\[\]\\:";''\<\>\?,\./]{0,128}$'

// (разница между первым и вторым — лишь в том, что символ «одинарная кавычка» удвоен (экранирован))

Функция, пытающаяся решить поставленную задачу у меня выглядит так:

Delphi
1
2
3
4
5
6
7
8
9
10
11
function PasswordIsValid(AText: String): Boolean;
 
const
  r = '^[a-zA-Z0-9`~!@#\$%\^&\*\(\)_\+-=\{\}\|\[\]\\:";''\<\>\?,\./]{0,128}$';
 
begin
  if TRegEx.IsMatch(AText, r) then 
    Result := True 
  else 
    Result := False;
end;
И все бы хорошо... Но печаль в том, то пустые строки эта функция валидными не считает, а должна бы... (повторений может быть от 0 до 128: {0,128}).

Я-то, кагбэ... нарисовал там "костыль", добавив дополнительную проверку на пустую строку, но теперь у меня душа не на месте, потому как это — перанальный подход:

Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
function PasswordIsValid(AText: String): Boolean;
 
const
  r = '^[a-zA-Z0-9`~!@#\$%\^&\*\(\)_\+-=\{\}\|\[\]\\:";''\<\>\?,\./]{0,128}$';
 
begin
  if Length(AText) = 0 then
    Result := True
  else if TRegEx.IsMatch(AText, r) then 
    Result := True 
  else 
    Result := False;
end;
Теперь спать спокойно не могу.

Какие мысли меня посещали:
- пустая строка в действительности не пустая... содержит какие-то символы, которые регулярное выражение "видит" и распознает как ин-валидные; ... как их увидеть?... как их оттуда убрать?..
- нужно использовать не "длинные строки" (String), а короткие: (String[128]); ... хотя, впрочем, что это даст....
- регулярные выражения в дельфийском модуле RegularExpressions имеют какой-то другой синтаксис, отличный от того, который принят в Expresso; ... как узнать, какой именно синтаксис использовать?..

Как победить это без "костыля", а так, чтобы было все красиво... - ума не приложу. Может быть, кто-то может что-то подсказать: в каком направлении исследовать?

(пытаться решать через использование библиотеки regexpr.pas (by Andrey V. Sorokin), или через импорт типов из библиотеки Microsoft VBScript Regular Expressions (как это описано тут — не хочу и не буду. Ибо это глупо, при условии, что есть "родной" модуль. А кроме того, там процедуры по пол-страницы (создать объекты, освободить память и все такое).)

Может ли кто-нибудь поделиться опытом и мастерством?...

P.S. Пишу на этом форуме впервые, но очень часто находил именно здесь полезную информацию, за что очень благодарен как организаторам форума, так и всем тем людям, которые делились знаниями и опытом. Большое спасибо вам!
__________________
Помощь в написании контрольных, курсовых и дипломных работ здесь
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
09.11.2013, 10:59
Ответы с готовыми решениями:

Delphi!? Регулярные выражения?
procedure TForm1.Button2Click(Sender: TObject); var s:string; i:integer; danye:array of...

есть ли в Delphi регулярные выражения?
есть ли в Delphi регулярные выражения?

Регулярные выражения в Delphi XE2
Добрый день, пишу парсёр имён и коментариев из открытых групп ВК, без авторизации. Надо удалить...

Регулярные выражения. Как вот такой код с php перевести на Delphi!?
$file = preg_match_all(&quot;|&lt;tr&gt;&lt;td class='time'&gt;(.*)&lt;/tr&gt;|U&quot;,$file,$frazes); $myper = array(); ...

5
Эксперт С++
8289 / 6120 / 613
Регистрация: 10.12.2010
Сообщений: 28,609
Записей в блоге: 30
09.11.2013, 18:02 2
Так тут регулярки не нужны, легче отсекать на этапе ввода, если ввод осуществляется например с Edit до то проще ограничить ввод других символов, т.е тупо что бы в компоненте не срабатывали пробел идр. клавиши.
Длину строки тоже мы можем узнать ...

А если нам нужна именно валидация с помощью функции то проще пройтись двойным циклом, ну ли одинарным с использованием множеств, и там же произвести замену запрещенных символов если нужно.
1
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
31243 / 20423 / 7960
Регистрация: 22.10.2011
Сообщений: 35,452
Записей в блоге: 6
09.11.2013, 18:09 3
mxmstn, qc.embarcadero.com/wc/qcmain.aspx?d=104562, поэтому совпадения нулевой длины не находятся... Костыль переписывается так:

Delphi
1
2
3
4
5
6
function PasswordIsValid(AText: String): Boolean;
const
  r = '^[a-zA-Z0-9`~!@#\$%\^&\*\(\)_\+-=\{\}\|\[\]\\:";''\<\>\?,\./]{0,128}$';
begin
  Result := (Length(AText) = 0) or TRegEx.IsMatch(AText, r);
end;
1
1 / 1 / 0
Регистрация: 09.11.2013
Сообщений: 7
09.11.2013, 20:55  [ТС] 4
Цитата Сообщение от Avazart Посмотреть сообщение
отсекать на этапе ввода, если ввод осуществляется например с Edit до то проще ограничить ввод других символов, т.е тупо что бы в компоненте не срабатывали пробел идр. клавиши.
У меня ситуация такая: за ввод пароля отвечает компонент класса TEdit, и там отсекается полностью ввод символов, которые не отвечают требованиям, указанным в первом посте. Однако, остается еще вставка (ctrl+v, shift+ins, а также клик на пункте "Вставить" в контекстном меню контрóла). Проблем нет — перехватить вставку. Но содержимое буфера обмена перед вставкой нужно проверить. И поэтому и нужна процедура проверки.

Цитата Сообщение от Avazart Посмотреть сообщение
А если нам нужна именно валидация с помощью функции то проще пройтись двойным циклом, ну ли одинарным с использованием множеств, и там же произвести замену запрещенных символов если нужно.
Проще, но не изящнее. Наверное, Вы согласитесь, Avazart, что написать одну строку текста — изящнее, чем два вложенных цикла. К тому же, у меня в программе требуется валидация и более сложных строк. Например, тот же IP. Поэтому изначально было принято решение работать именно с регулярными выражениями. И вместо того, чтобы писать «безумные» проверки, ведь намного изящнее записать:

Delphi
1
TRegEx.IsMatch(проверяемый_текст, регулярное_выражение);
... чем городить огород из циклов, множеств, и всевозможных условий.

Тем не менее, Вам, Avazart большое спасибо за то, что не остались равнодушны к моей проблеме. Сказать по правде, я и не ожидал, что раньше чем через неделю кто-то напишет мне ответ.



Цитата Сообщение от UI Посмотреть сообщение
mxmstn, qc.embarcadero.com/wc/qcmain.aspx?d=104562, поэтому совпадения нулевой длины не находятся...
UI, нет слов, чтобы выразить Вам мою благодарность! Все теперь понятно. Теперь можно спать спокойно! И, несмотря на то, что «костыль» все-таки придется оставить (предложенный Вами вариант записи «костыля», опять же, намного лаконичнее и изящнее), но я теперь хотя бы знаю, ПОЧЕМУ ТАК!!

З.Ы. Когда прочитал Ваше сообщения, то на радостях предпринял попытку переписать ядро... Ну, а точнее, файл System.RegularExpressionsCore.pas в папке C:\Program Files (x86)\Embarcadero\RAD Studio\12.0\source\rtl\common, с тем, чтобы в методе создания TPerlRegEx.Create заменить

Delphi
1
FState := [preNotEmpty];
на

Delphi
1
FState := [];
Естественно же, зафэйлился... так как заменить-то я заменил, а вот перекомпилировать не смог... наверное, и к счастью. Побоялся лезть глубже, и решив, что не моего уровня это дело, просто оставил «костыль» как Вы предложили.

Но теперь-то, благодаря Вам, я хоть знаю, почему он там нужен!!!
Низкий поклон! Огромный и искренний респект!
0
Эксперт С++
8289 / 6120 / 613
Регистрация: 10.12.2010
Сообщений: 28,609
Записей в блоге: 30
09.11.2013, 21:13 5
Цитата Сообщение от mxmstn Посмотреть сообщение
Проще, но не изящнее. Наверное, Вы согласитесь, Avazart, что написать одну строку текста — изящнее, чем два вложенных цикла. К тому же, у меня в программе требуется валидация и более сложных строк. Например, тот же IP. Поэтому изначально было принято решение работать именно с регулярными выражениями. И вместо того, чтобы писать «безумные» проверки, ведь намного изящнее записать:
Согласен, регуляки прежде всего гибкость, к примеру их можно подгружать с файла, а значить менять поведение программы в каких-то рамках без перекомпиляции самой программы, но не всегда регулярки очевидны и не всегда подходят по скорости их работы.
1
1 / 1 / 0
Регистрация: 09.11.2013
Сообщений: 7
09.11.2013, 21:18  [ТС] 6
Цитата Сообщение от Avazart Посмотреть сообщение
Согласен, регуляки прежде всего гибкость, к примеру их можно подгружать с файла, а значить менять поведение программы в каких-то рамках без перекомпиляции самой программы, но не всегда регулярки очевидны и не всегда подходят по скорости их работы.
Это — да. Еще раз спасибо! И Вам, опять же, респект! По скорости у меня вопрос остро не стоит. Но вот, то, что Вы написали о возможностях менять поведение программы таким путем, — дает мне дополнительную пищу для размышлений! Спасибо!
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
09.11.2013, 21:18

Delphi и регулярные выражения! Почему ошибка эта постоянно, не понимаю, см. код?
unit unAnal; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics,...

Регулярные выражения System.RegularExpressions (Delphi XE3/FireMonkey)
Здраститя. Есть такая строка &quot;&lt;message&gt;SUCCESS_YES&lt;/message&gt;&quot; Значение тега, меняется в...

Регулярные выражения. Подсветка синтаксиса.
Подскжите как составить выражение для поиска точного слова в строке. string = &quot;sum min max&quot; ...

Регулярные выражения - Редактор с подсветкой синтаксиса
доброго времени суток. Помогите разобраться с проблемой. Пишу курсовой проект &quot;Редактор с...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
6
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2021, vBulletin Solutions, Inc.