5 / 10 / 3
Регистрация: 05.10.2010
Сообщений: 97
1

Проверка валидности строк с помошью регулярных выражений

05.10.2010, 18:27. Показов 8584. Ответов 8
Метки нет (Все метки)

Здравствуйте. Возникла такая проблема: есть определённый набор строк, задано регулярное выражение. Необходимо проверить валидность строк. Это делается естественно не сложно. Но я перерыл полинтернета и так и не нашёл, как с помощью стандартных функций узнать, в каком именно месте строки начинается несовпадение с регулярным выражением. То есть вопрос такой: как определить до какого места в строке, есть совпадение с регулярным выражением?
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
05.10.2010, 18:27
Ответы с готовыми решениями:

Массив регулярных выражений
Как сделать регулярное выражение которое бы считывало все теги и подтеги файла? Я делал вот такое -...

Как оптимизировать применение регулярных выражений
Как оптимизировать следующий код? string a2 = Regex.Replace(x, p, @"$4",...

Проверка наличия и валидности DLL при старте приложения
Есть C#.NET DLL (моя), которая является оберткой над C++ DLL(не моя). Я использую ее(их получается)...

Проверка "валидности" ссылки средствами ASP
Как средствами АСП (ну, или, в крайнем случае, ЯваСкрипт) сделать вот что: Проверить адрес...

8
Padawan
473 / 323 / 30
Регистрация: 30.01.2010
Сообщений: 1,841
05.10.2010, 22:15 2
Пользуйся этим
0
1507 / 774 / 103
Регистрация: 22.04.2008
Сообщений: 1,610
05.10.2010, 22:17 3
Дайте тестовые данные и регулярное выражение и поможем.
0
5 / 10 / 3
Регистрация: 05.10.2010
Сообщений: 97
05.10.2010, 22:21  [ТС] 4
Вот регулярное выражение:
@"([А-Я][а-я]+ ){3}\s*((0[1-9])|(1\d)|(2\d)|(3(0|1))).((0[1-9])|(1(0|1|2))).19\d\d\s+\d{7}(\d{3})?"
Ну примерно так: Фамилия Имя Отчество дата телефон.
Только какая разница как оно выглядит? Мне интересно какие методы борьбы есть с моей проблемой.

Тестовые данные:

Иванов Петр Николаевич 18.12.1988 9213333333
Иванов Петр Николаевич 18.12.1988 9213333333
Петров Николай Иванович 1987.10.18 7561111
Николаев Иван Петрович 01.12.1989 564444
Андреев Семен Борисович 03.07.1988 9115555555
Семенов Борис Андреевич 12.23.1988 35622223
Борисов Андрей Cеменович 10-10-1988 9602222222
Александров Павел Викторович 22.10.1988 3253344

Я бы для решения моей проблемы реализовал конечный автомат. Но необходимо использование именно регулярных выражений.
0
1507 / 774 / 103
Регистрация: 22.04.2008
Сообщений: 1,610
05.10.2010, 22:29 5
А регулярные выражения и построены на конечных автоматах.
Как я понял вам надо узнать в каком месте в строке данные не подходят шаблону.
я думаю вам не надо тестировать одним регулярным выражением, а разбить на несколько
например одно для тестирования ФИО другое Телефон и т д
и вы будете знать что именно у вас не соответствует шаблону

Добавлено через 1 минуту
Можете и одним только используйте именнованные группы
C#
1
string regex = @"(?<FIO>...)(?<Phone>...)";
где будет не совпадение будет пусто.
0
76 / 73 / 9
Регистрация: 09.06.2010
Сообщений: 206
06.10.2010, 01:20 6
У экземпляра Match есть свойства Index и Length - начало и длинна совпадения в тексте
Но я то же склоняюсь к именованым группам

По регулярке
Цитата Сообщение от dmz Посмотреть сообщение
@"([А-Я][а-я]+ ){3}\s*((0[1-9])|(1\d)|(2\d)|(3(0|1))).((0[1-9])|(1(0|1|2))).19\d\d\s+\d{7}(\d{3})?"
Видемо выделенный текст должен соответствовать ФИО, но совпадения не будет, тк пробельный символ идет только после 3-х буквенных групп, а не между ними
0
5 / 10 / 3
Регистрация: 05.10.2010
Сообщений: 97
06.10.2010, 23:04  [ТС] 7
хорошо, я узнаю в какой именно группе есть несовпадение. А как узнать индекс символа который не совпадает?

Добавлено через 18 часов 15 минут
Просто автомат без всяких проблем может сказать в каком месте строка перестаёт быть валидной. Регулярные выражения основаны на автоматах, как было замечено выше, но при этом я не могу найти стандартного метода который бы четко давал ответ, где строка перестаёт удовлетворять регулярному выражению. Очевидно же, что это может понадобиться в некоторых задачах, так что я не могу поверить, что стандартным интерфейсом это не предусмотрено.
0
76 / 73 / 9
Регистрация: 09.06.2010
Сообщений: 206
07.10.2010, 04:22 8
Рег.в. ищет совпадения в тексте. Если совпадения нет, то оно ничего не найдет
Значит можно выделить "отрезки" на которых нет совпадения - при условии правильной регулярки и предположения что блоки совпадения должны следовать друг за другом

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
static void Main(string[] args)
        {
            string s = @"Иванов Петр Николаевич 18.12.1988 9213333333
Иванов Петр Николаевич 18.12.1988 9213333333 
Петров 123 1987.10.18 7561111
Николаев Иван Петрович 01.12.1989 564444
АндреевСеменБорисович 03.07.1988 9115555555
Семенов Борис Андреевич 12.23.1988 35622223
Борисов Андрей Cеменович 10-10-1988 9602222222
Александров Павел Викторович 22.10.1988 3253344
Абракадабра)))) 12-12-12 1111";
 
            string pattern = @"\s*(?<ФИО>\w+\s+\w+\s+\w+)\s+(?<Дата>\d{2,4}[/\-\.]\d{2}[/\-\.]\d{2,4})\s+(?<Телефон>\d+)\s*";
 
            Regex regex = new Regex(pattern);
 
            Match match = regex.Match(s);
            string[] names = regex.GetGroupNames();
            int prevIndex = 0;
            while(match.Success)
            {
                if (prevIndex != match.Index)
                {
                    string no = s.Substring(prevIndex, match.Index-prevIndex);
                    Console.WriteLine("********************************************************************************");
                    Console.WriteLine("Не совпавшая строка: \"{0}\"\nIndex = {1}, Length = {2}", no, prevIndex, match.Index - prevIndex);
                    Console.WriteLine("********************************************************************************");
                    Console.WriteLine();
                    Console.WriteLine();
                }
 
                Console.WriteLine("Полное совпадение с: \"{0}\"",match.Value);
                Console.WriteLine("Index = {0}, Length = {1}", match.Index, match.Length);
                Console.WriteLine();
                Console.WriteLine("Именованные группы:\n");
                foreach (string name in names)
                {
                    Group group = match.Groups[name];
                    Console.WriteLine("\tmatch.Groups[\"{0}\"] = {1}", name, group.Value);
                    Console.WriteLine("\tIndex = {0}, Length = {1}", group.Index, group.Length);
                    Console.WriteLine();
                }
                prevIndex = match.Index + match.Length;
                match = regex.Match(s,match.Index+match.Length);
                Console.WriteLine("\n\n\n");
            }
            if (prevIndex < s.Length-1)
            {
                string no = s.Substring(prevIndex, s.Length - prevIndex);
                Console.WriteLine("********************************************************************************");
                Console.WriteLine("Не совпавшая строка: \"{0}\"\nIndex = {1}, Length = {2}", no, prevIndex, s.Length - 1);
                Console.WriteLine("********************************************************************************");
                Console.WriteLine();
                Console.WriteLine();
            }
            Console.ReadKey();
        }
Для поиска ошибок в каждой группе необходимо будет делать еще допущения.
Например, "Александров Павел Викторович 22.10.1988 3253344" и "Павел Викторович Александров 22.10.1988 3253344" - фамилия в другом месте,
не каждый человек отличит фамилию от имени. Или дата 12-12-12.
Необходимо составить список возможных "ошибок" в тексте, соответственно сложность обработки возрастет.
Можно написать несколько регулярок для проверки ошибок, и ими проверять куски, которые получены в предыдущем примере
Или поискать более простые пути.

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

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
static void Main(string[] args)
        {
            
            Regex[] regexes = new Regex[]{
                    new Regex(@"^\s*(?<ФИО>\w+\s+\w+\s+\w+)\s+",RegexOptions.Compiled|RegexOptions.Singleline),
                    new Regex(@"(?<Дата>\d{2,4}[/\-\.]\d{2}[/\-\.]\d{2,4})\s+",RegexOptions.Compiled|RegexOptions.Singleline),
                    new Regex(@"(?<Телефон>\d+)\s*$",RegexOptions.Compiled|RegexOptions.Singleline)}; 
 
            string[] ss = new string[] { "Иванов Петр Николаевич 18.12.1988 9213333333",
                                         "Петров 123 1987.10.18 7561111",
                                         "Иванов Петр Николаевич 18w12w1988 9213333333",
                                         "Иванов Петр Николаевич 18-12-1988 921u3333333"};
 
            foreach (string s in ss)
            {
                int prevInd = 0;
                Console.WriteLine("Строка: {0}", s);
                for (int i = 0; i < regexes.Length; i++)
                {                    
                    Match m = regexes[i].Match(s, prevInd);
                    if (m.Success && prevInd == m.Index)
                    {
                        string[] names = regexes[i].GetGroupNames();
                        Console.WriteLine("Выражение \"{0}\" совпало: \"{1}\"", regexes[i].ToString(), m.Groups[names[1]]);
                        prevInd = m.Index + m.Length;
                    }
                    else
                    {
                        Console.WriteLine("Выражение \"{0}\" не совпало с \"{2}\". Начало несовпадения: {1}", regexes[i].ToString(), prevInd, s.Substring(prevInd, s.Length - prevInd));
                        break; // Дальше можно не проверять
                    }
                }
                Console.WriteLine();
            }
 
            Console.ReadKey();
        }
2
5 / 10 / 3
Регистрация: 05.10.2010
Сообщений: 97
07.10.2010, 20:49  [ТС] 9
Благодарю)
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
07.10.2010, 20:49
Помогаю со студенческими работами здесь

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

Проверка строки с пом. регулярных выражений
Необходимо чтобы программа определяла верно ли введено выражение вида Ax+By+Cz. Кофициенты должны...

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

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


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

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

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2023, CyberForum.ru