Все технические форумы на одном сайте Удобный поиск информации с популярных форумов в одном месте
Вопрос: Регулярные выражения FAQ

Как и обещал, выкладываю свой FAQ по Regex для тех кто только начинает с ним знакомиться. По мере углубления своих знаний готов продолжить работу над ним. Если администрации он покажется полезным то можно вынести тему наверх. Надеюсь что кому-то он поможет, мне бы, во всяком случае, для старта он очень пригодился бы.

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


Regex FAQ.


Регулярные выражения – это один из способов поиска подстрок (соответствий) в строках. Осуществляется это с помощью просмотра строки в поисках некоторого шаблона.
Для того чтобы использовать Regex в своих программах необходимо в список используемых пространств имен добавить:
using System.Text.RegularExpressions;
Далее, в коде самой программы необходимо создать экземпляр Regex:
Regex newReg = new Regex(pattern,options);
Все найденные соответствия в тексте помещаются в тип MatchCollection
MatchCollection matches;
И далее в этот объект поместить текст, в котором необходимо произвести поиск:
matches = optionRegex.Matches(text);
В результате в matches появляются все результаты парсинга. Мы можем посмотреть сколько их (matches.Count), можем узнать значение конкретного элемента (matches[N].Value)
pattern – образец или условие для поиска, например, если необходимо найти слово“не” в строке “не может быть”, то pattern для поискабудет выглядеть так: @"не". В простейшем случае, можно обойтись без условия поиска, тогда найдено будет значение точно повторяющее pattern. Можно получить как значение найденного совпадения так и их количество, как видно из примера ниже.
C#
1
2
3
4
5
6
7
8
9
string pattern = @"не";
string text = "не может быть"; 
Regex newReg = new Regex(pattern);  
MatchCollection matches = newReg.Matches(text);
foreach(Match mat in matches)
{
    Console.WriteLine("Значение найденного обьекта {0}",mat.Value);
}
Console.WriteLine("Число найденных совпадений{0}",matches.Count);
Теперь остановимся на условиях поиска, или options. Для начала необходимо создать условие поиска:

RegexOptions option = RegexOptions.<условие поиска>;
Ниже приведены условия поиска.
IgnoreCase – находит совпадения независимо от регистра, т.е. прописными или строчными буквами в строке написано слово.
IgnorePatternWhitespace – устраняет из шаблона неизбежные пробелы и включает комментарии помеченные «#».
Compiled – указывает что регулярное выражение скомпилировано в сборку. Это порождает более быстрое исполнение но увеличивает время запуска.
CultureInvariant – указывает игнорирование региональных языковых различий.
ExplicitCapture – указывает что единственные допустимые записи являются явно поименованными или пронумерованными группами в форме(?<name>…)
Multiline – Многострочный режим. Изменяет значения символов “^” и“$” так что они совпадают соответственно в начале и конце каждой строки, а не только в начале и конце целой строки.
RightToLeft – указывает что поиск будет выполнен справа на лево, а не слева на право.
Singleline – однострочный режим.
None – указывает на отсутствие заданных параметров.
Пример с условиями поиска будет выглядеть так:
C#
1
2
3
4
5
6
7
8
9
10
string pattern = @"не";
string text = "Не может быть совсем не может быть"; 
RegexOptions option=RegexOptions.IgnoreCase; 
Regex newReg = new Regex(pattern,option);  
MatchCollection matches = newReg.Matches(text);
foreach(Match mat in matches)
{
     Console.WriteLine("Значение найденного обьекта {0}",mat.Value);
}
Console.WriteLine(“Число найденных совпадений{0}”,matches.Count);
В этом случае будет осуществлен поиск слова “не” не зависимо от того какими буквами (прописными или строчными) оно написано. И в результате будут найдены оба слова в строке. При желании и опыте, код может быть оптимизирован.
Используя специальные символы можно создавать более сложные шаблоны для поиска:
^ - указывает на то, что поиск должен начинаться с начала строки, например шаблон (@”^не”) найдет “не” в строке, если она начинается с него: “Не может быть совсем не может быть не”.
$ -указывает на то что поиск должен производиться в конце строки, шаблон (@”не$”) найдет “не” в той же самой строке, только если она заканчивается им.
{n} – указывает точное число вхождений в строку, например шаблон (@"не{2}") найдет слово “нее” в строке.
{n,} – указывает число вхождений не менее n, т.е. шаблон (@"не{2,}") найдет слова “нее”, “неее” и т.д.
{n,m} – указывает число вхождений-n и количество символов вхождения-m, то есть шаблон (@"не{2,4}") найдет все слова где количество букв “е” больше 2, но определит только количество букв ”е” равное 4. Т.е. в слове “нееееееееее” он найдет только “нееее”.
+ - Соответствует 1 или более предшествующих выражений. Например, "не+" соответствует "не" и "нее", но не соответствует "н".
*- Соответствует 0 или более вхождений предшествующего выражения. Например, 'не*' соответствует "н" и "нее".
? - Соответствует 0 или 1 предшествующих выражений. Например, 'бы(ло)?' соответствует "бы" в "бы" или "было".
В квадратных скобках можно указать диапазон букв или цифр для поиска, например [A-Z] или [0-9]
Далее приведен пример для поиска времени в формате 00:00:00 и показана некоторая оптимизация кода.
C#
1
2
3
4
5
6
7
8
string s1 = "Не время для драконов 00:00:00";
            Regex reg = new Regex(@"[0-9]+:[0-9]+:[0-9]+",RegexOptions.IgnoreCase);
            MatchCollection mc = reg.Matches(s1);
            foreach (Match mat in mc)
            {
                Console.WriteLine(mat.ToString());
            }
            Console.WriteLine(mc.Count.ToString());
Ответ: Посмотрел первую и вторую ссылку для проверки регулярных выражений. Обе не понравились.
Потратил драгоценное время и накидал маленькую програмку для проверки регулярных выражений.
Прикладываю вместе с исходниками кому надо.

PS Програмка на C# так что все выражения что в ней работают, работают в C#
Вопрос: Проверка логина регулярным выражением

Валидные логины, например:
a-a, a00, aaa-a, a_a, aaa, aaa0000-a, a-a-a, a-a_a
Невалидные логины, например:
-a, --a, -aa, aa-, a-, a0-, aaa_, a-_, a____-a, a_-
От 3 до n символов

Помогите с данным регулярным выражением, пожалуйста.

Я наверное (да не наверное, а точно), буду миллионным человеком, который это спрашивает, но все же... Перерыл "весь" интернет, потратил достаточно много времени, чтобы найти ответ на вопрос: и на данном сайте в том числе, но так и не добрался до истины. Читал документацию по регулярным выражениям, но ничего не понял. Вопрос очевиден, исходя из названия темы: как проверить логин на валидность с помощью регулярных выражений?

Проблема в том, что, например, такое выражение меня не устраивает: "/^[a-zA-Z0-9_-]{3,15}$/", так как пропустит
2f22---
или
---22a1
Наиболее подходящая проверка: "/^[a-z]+([-_]?[a-z0-9]+){0,2}$/i", но она не пропускает
f-f
и нет границ от 3 до n символов.

Что мне нужно:
Как на любом порядочном сайте первый символ логина должен быть латиницей,
Затем может использоваться латиница, цифры или _ и -, но нельзя им стоять вместе, например: "-_" или "--" или "_-".
Также логин не должен заканчиваться дефисом или нижним подчеркиванием, только латиницей или цифрами
И в заключении логин должен быть от 3, до 15 (например) символов.

Валидные логины, например:
a-a, a00, aaa-a, a_a, aaa, aaa0000-a, a-a-a, a-a_a
Невалидные логины, например:
-a, --a, -aa, aa-, a-, a0-, aaa_, a-_, a____-a, a_-
От 3 до n символов

Добавлено через 56 минут
Я короче все очень сложно объяснил, дайте нормальное регулярное выражение для логина со всеми плюшками, пожалуйста.
Ответ:
Сообщение от GladiatoR-13
Что мне нужно:
Как на любом порядочном сайте первый символ логина должен быть латиницей,
Затем может использоваться латиница, цифры или _ и -, но нельзя им стоять вместе, например: "-_" или "--" или "_-".
Также логин не должен заканчиваться дефисом или нижним подчеркиванием, только латиницей или цифрами
И в заключении логин должен быть от 3, до 15 (например) символов.
А обязательно описывать это все одним регулярным выражением?

Куда легче и нагляднее проверять каждый пункт по отдельности. Тем более, таким образом добавить или исключить один из пунктов будет куда легче, нежели переделывать регулярку...
PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php
function check($s)
{
    $len = strlen($s);
    if ($len < 3 || $len > 15)
        return false;
    if (!preg_match("/^[a-z0-9][a-z0-9-_]+[a-z0-9]$/is", $s))
        return false;
    foreach (["--", "__", "-_", "_-"] as $v)
        if (strpos($s, $v))
            return false;
    return true;
}
 
$a = ['a-a', 'a00', 'aaa-a', 'a_a', 'aaa', 'aaa0000-a', 'a-a-a', 'a-a_a', '-a', '--a', '-aa', 'aa-', 'a-', 'a0-', 'aaa_', 'a-_', 'a____-a', 'a_-'];
 
foreach ($a as $v)
    printf("Nickname <b>%s</b> is <b>%s</b>!<br>\n", $v, check($v) ? "valid" : "invalid");
Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Nickname a-a is valid!
Nickname a00 is valid!
Nickname aaa-a is valid!
Nickname a_a is valid!
Nickname aaa is valid!
Nickname aaa0000-a is valid!
Nickname a-a-a is valid!
Nickname a-a_a is valid!
Nickname -a is invalid!
Nickname --a is invalid!
Nickname -aa is invalid!
Nickname aa- is invalid!
Nickname a- is invalid!
Nickname a0- is invalid!
Nickname aaa_ is invalid!
Nickname a-_ is invalid!
Nickname a____-a is invalid!
Nickname a_- is invalid!
Вопрос: Регулярное выражение вместо алгоритма

Всем доброго времени суток.

Такой вот вопрос. Начал изучать регулярные выражения но не могу добиться нужного результата.
Есть номер сотого телефона, нужно его на валидность проверить. Случай довольно простой нет скобок, +, кодов города,
страны , городских номеров и т.д. - Все ,что нужно:
1 - В номере только 11 цифр
2- Первая цифра 7 либо 8 (причем если 8 меняем на 7)
3- Вторая цифра 9
4- В номере не может присутствовать больше 4 одинаковых цифр подряд ( Вот здесь на "регулярке" я и сподкнулся )

На уровне алгоритма я написал, это довольно быстро
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
 f:=True; n_equal:=0;
            if Length(phone) in Size_Tel then begin
               for i:= 1 to Length(phone)  do
                   begin
                   if  not ((phone[i] >= '0') and (phone[i] <= '9')) then begin f:= False; Break; end;
                   if (i=1) and (not StrToInt(phone[i]) in [7,8])    then begin f:= False; Break; end;
                   if (i=1) and (phone[i]='8') then StringReplace(phone,'8','7',[]);
                   if (i=2) and (phone[i]<>'9')                      then begin f:= False; Break; end;
                   if (i>1) then begin if phone[i]=phone[i-1] then inc(n_equal) else n_equal:=0;  end;
                   if n_equal>=5                                     then begin f:= False; Break; end;
                   end;
            end else f:= False;
Но если применить регулярное выражение то этот код можно заменить, на что то вроде

Delphi
1
if RegEx.IsMatch(phone,'((8|7)(\(?\d{3}\)?[\- ]?)?[\d\- ]{7,10}')  then
Первые три пункта - тривиальны, но 4й меня вгоняет в ступор и тут 2 варианта
1- решение есть, оно адекватных трудо затрат но ускользает от меня по причине отсутствия опыта с регулярками
2- для данного случая регулярку лучше вообще не юзать

Прошу совета - заранее благодарен.
Ответ:
(?!=.*0{5}
Там знак равно лишний.

(?!regex) - негативная опережающая проверка.
(?=regex) - позитивная опережающая проверка.


(\d)\1{5}
Круглые скобки "запоминают" текст, совпавший с находящимся в них подвыражением,
а с помощью обратных ссылок можно проверить совпадение с этим текстом в любом месте регулярного выражения.
Выражение (\d)\1{5} находит цифру, за которой следует еще 5 повторений этой цифры. Итого 6 одинаковых цифр подряд.

Могу посоветовать книгу "Регулярные выражения" автор Джеффри Фридл.
Ян Гойвертс, Стивен Левитан - Регулярные выражения. Сборник рецептов.
Вопрос: Регулярные выражения

Добрый день, помогите пожалуйста разобрать регулярное выражение (@"(\w)\1+").

(\w) - цифра, буква или знак подчеркивания
+ - встречается 1 или более раз.
это я нашел и понял. Но что такое \1 - найти не смог. Объясните пожалуйста что означает эта часть регулярного выражения.

Заранее спасибо.
Ответ: Фарад, первые окружающие скобки в данном случае - это синтаксис вызова конструктора класса Regex:

C#
1
Regex expression = new Regex ( ... ) ;
Символ @ перед строкой указывает, что компилятор должен воспринимать её (строку) "как есть" (то есть как любую последовательность символов до следующей двойной кавычки).
Таким образом, мы опять же приходим к тому, что оригинальное регулярное выражение - то, что расположено между двойными кавычками: (\w)\1+. Этому регулярному выражению будут соответствовать строки вида "dddd", "1111" и т. д.
Вопрос: анализ регулярных выражений

Доброго времени суток коллеги)

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

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

а задача в том, чтобы анализируя регулярное выражение получать максимальную и минимальную длину строки, которая могла бы подойти под эту регулярку, и всевозможные символы, которые она предусматривает
Вопрос: При извлечении регулярного выражения из 'datatable' в переменную типа 'string' добавляются слэшы

Опишу весь сценарий

1. Вношу регулярное выражение в 'dataGridView' - '(?<=<div\ class="actual-project-item-h"><a\ href=").*?(?=">)'
2. Из 'dataGridView' оно сохраняется в 'datatable' и 'Settings.settings'
3. Извлекаем из 'datatable' в переменную типа 'string'.
4. Получаем регулярное выражение '(?<=<div\\ class="actual-project-item-h"><a\\ href=").*?(?=">)'

КОД
C#
1
2
3
4
foreach (DataRow row_pl in dt_029_cmp.Rows)
            {     
               string str_pl_rgvr = row_pl["pl_rgv"].ToString();
             }
Сравнение.
Вношу в 'dataGridView' в виде - '(?<=<div\ class="actual-project-item-h"><a\ href=").*?(?=">)'
Извлекается из 'datatable' в виде - '(?<=<div\\ class="actual-project-item-h"><a\\ href=").*?(?=">)'


Вопрос.
Почему добавляются слэшы?
Как сделать чтобы извлекалось регулярное выражение такое же как и вносимое?
Ответ: zakaz_77, не знаю. Возможно входная строка другая, возможно в регулярном выражении ошибка. Сравни значения с помощью отладчика.

И, кстати, парсить html регулярками плохая идея. Лучше использовать специализированные библиотеки. Например, .
Вопрос: Помогите исправить регулярное выражение

Добрый день! Подскажите, пожалуйста, в чем ошибка.
Нужно выделить отдельно минуты и отдельно часы в выражении а-ля crontab
Например
Код

15 12 * * *

15,45 12 * * *

15,45,30 12,18,22 * * *

15,45,30,35 12,18,22,23 * * *

Количество элементов в списке минут и списке часов не ограничено.
Первый блок — минуты 0..59 через запятую без пробелов, затем пробел — и аналогично список часов 0..23. Далее пробел и через пробелы три звездочки.
Мне нужно получить список минут и список часов, например:
Код

15,45,30,35 12,18,22,23 * * *

в результате должно быть: 
Код

«15», «,45», «,30»,  «,35», « », «12», «,18», «,22», «,23» 
(пробел выделяю для того, чтобы отделить минуты от часов, запятые убираю потом — но если можно сделать сразу без них, было было отлично).
Мое регулярное выражение:
Код

^([1-5][0-9]|[1-9])([,][1-5][0-9]|[,][1-9])*(\\s)([1-2][0-9]|[1-9])([,][1-2][0-9]|[,][1-9])*\\s[*]\\s[*]\\s[*]$

Совпадение находит,однако в результате
Код

    0: 15,45,30,35 12,18,22,23 * * *

    1:  15

    2:  ,35

    3:

    4: 12

    5:  ,23

Ответ:
Все правильно. Вас интересуют группы 1,2,5 и 6. По запятым вам придется резать самому. Группы в регулярном выражении статически определяются скобками (1 группа - 1 пара скобок), а так как количество чисел в списках через запятую статически неизвестно, то для их отдельного выделения группы в регулярных выражениях не пригодны.

Вопрос: Помогите составить регулярное выражение

Не могу правильно составить регулярное выражение.

Есть примерно такая строка
-24x+1a-6xy-1b-10

Нужно заменить все 1 перед которыми стоят буквы, не трогая сами буква.

У меня такое регулярное выражение:
PHP:

  1. ('/(1)[a-z]+/', '', $answer);


Нужные подстроки находит, но при замени захватывает и буквы после 1-цы.
Ответ:
[quote=Строитель][/quote], нет, мне не все единицы нужно заменить, а только одну, перед которой нет других цифр и после которой идут буквы. Моя вина, не уточнила сразу.
Ваша выражение работает, но можно его дополнить нужными условиями?

Я попробовала дописать вот так, но увы, этот вариант не работает.

PHP:

  1.  
  2. $answer = '1cc+5x-9+1a-6xy-23x-21b';
  3. ('~([^\D]1{1}([a-z]+))~', '$2', $answer);
  4.  

(Добавление)
Fart пишет:

зачем нужна регулярка и вообще такая обработка строки если данные статичны? Не понял


Данные динамичные, почему вы решили, что они статичные?

Цитата:

приведенная выше регулярка нарушает полином. если это какие то работы с полиномами... то вид полинома до -24x+1a-6xy-11b-10 и после -24x+a-6xy-b-10 - нарушает его целостность.


А вот это да, я не учла...
Нужно тогда, чтобы регулярное выражение искала одну 1-цу перед которой не стоят другие цифры и после которой идут только буквы.
Это возможно?

(Отредактировано автором: 07 Ноября, 2016 - 08:27:06)

Вопрос: Регулярное выражение

Регулярные выражения совсем не знаю, нужно в $div убрать все квадратные скобки, в которых цифры (обычно они сразу после слов или после дат), делаю примерно вот так
Код:
$div=preg_replace("/[\d+]/"""$div);
echo 
$div->plaintext
, но $div тогда совсем пустой, как правильно?
Ответ:
DemoN1810 писал(а):просто не понимаю
вот именно. я просто хотел услышать от тебя логику написанного тобой чуть выше регулярного выражения. ведь регулярное выражение легко описывается обычным русским языком. я не услышал от тебя обычного русского языка. значит ты не хочешь чтоб тебе помогали с исправлением твоих "знаний". сделал и сделал. работает? ну и хорошо. рад за тебя.
Вопрос: Создании регулярного выражение

Я в джава новичок и не когда не работал с регулярными выражениями.

Есть строка
F#
1
""id":206718994,"first_name":"FN","last_name":"AllPeng","type":"private"},"date":1460271321,"text":"Привет "}}"
Мне нужно извлечь Привет .


заранее спасибо .
Ответ: я вам предлагаю сесть и разобраться, прочитать статейку и набросать очень простых примером.
1) это конечно сначала поработать со строкой, извлечь первое вхождение String.indexOf и String.lastIndex
2) после разобраться со Pattern and match
и уделить часа 2-3 на всякие частые операции, типа проверки ип ,самому написать ,и потом посмотреть реальное регулярное выражения для поиска ип., оно большое. потом поискать в тотал командаре файлы, там тоже используются регулярные выражения.
Говорят если научишься один раз пользоваться, то в дальнейшем тоже сможешь использовать, а жизнь то она длинная.