Секреты регулярных выражений

Ответить
Аватара пользователя
Fenix
Администратор

Секреты регулярных выражений

#1

Сообщение Fenix » 20 июн 2018 16:30

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

Алексей Снастин
В данной теме будем обсуждать правила на основе рег. выражений.
Что получится если?.. почему не получается если?.. :wall:


:pdf icon: Д. Фридл "Регулярные выражения" (3-е издание)

Данная книга откроет вам секрет высокой производительности. Тщательно продуманные регулярные выражения помогут избежать долгих часов утомительной работы и решить свои проблемы за 15 секунд. Ставшие стандартной возможностью во многих языках программирования и популярных программных продуктах, включая Perl, PHP, Java, Python, Ruby, MySQL, VB.NET, C# (и других языках платформы .NET), регулярные выражения позволят вам автоматизировать сложную и тонкую обработку текста.



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

:pdf icon: Смотреть шпаргалку

Аватара пользователя
evmir_troll-hunter
Администратор

Re: Секреты регулярных выражений

#2

Сообщение evmir_troll-hunter » 28 июн 2018 21:24

wasyaka писал(а): Jan 14 2018

Почему так:
рег выражение (\bвс)е\b(\s([А-Яа-яёЁ\-]+))?(\s([А-Яа-яёЁ\-]+))?(\s([А-Яа-яёЁ\-]+))?(\s\b(мелочи|мелочи)\b)=$1<:yo:>$2$4$6$8

срабатывает во всех случаях - от все мелочи до все 1-3 слова мелочи
но только при условии что $8 (последжние скобки) из двух и более слов?
Хорошая штука научный тык (2часа тыкал, брал одно слово и тЭстировал... :wall: вместо :russian: хорошо догадался совместить...), но всё же, почему? :scratch:

Аватара пользователя
MoppoH
Постоялец

Регулярные выражения, что и как

#3

Сообщение MoppoH » 24 июл 2018 20:48

Очень интересное обсуждение рег выражений пошло у нас [...] предлагаю скидывать свои выражения, обсуждать как улучшить чужие.
wasyaka писал(а):
24 июл 2018 12:23
\s?(\w+)? -? означает может присутствовать, а может и нет
вот тут не понял, что после \s может еще присутствовать там между двумя словами?
tonio_k писал(а):
24 июл 2018 13:48
- в среднем длина слова в русском языке - 7 символов. 10 - это я с расчетом на "чуть выше средней" длины слова.
как показала многолетняя практика рассчитать количество символов практически не возможно, сейчас стараюсь уйти от этого вот таким путем
(?i)\bвсе\b(?=.[\S]*(апно|асно|енно|ично|ливо|ль[кн]о|стро|точно)\b.[\S]+(!али|атся|ают|(в|м|н|ч)али|ваны|дели|емся|\Bили|лены|лись|нили|сели|ыкли|яли|ятся)\b)
а то часто бывают ложные срабатывания
wasyaka писал(а):
24 июл 2018 12:23
( \s(\w+)?){1,}) - используется всё предложение (пропущенные(не использованные для правила) слова до ключевого заменяются пробелом) и это грубое правило, ниже(далее) по словарю более точные и т.д. отсюда и \s{1,4}, в отличии от KoobAudio где срабатывание на "первом встречном" и как бы наизнанку от точного к размытому .Из-за этого я и отказался от проги и перешёл на REX.
чем плохо что используется все предложение, тем что оба слова уже забиты одним рег выражением, и если допустим прилагательное + омограф уже найдено, то это прилагательное уже не пойдет к другому омографу
типа такого, дырявые трубы или печи, заменит только один из омографов
tonio_k писал(а):
24 июл 2018 01:55
Не спорю хитро сделано в итоге знак "< " на последнюю букву для каждого слова на конце, что для Николая - самое то, а вот для Максима - не подходит.
не понял в чем проблема со знаком <, можно добавить в словарик для Максима такое выражение
\Bы<=Ы, и после обработки он заменит все < на большие буквы для Максима

Аватара пользователя
tonio_k
V.I.P.

Регулярные выражения, что и как

#4

Сообщение tonio_k » 24 июл 2018 21:33

MoppoH писал(а):
24 июл 2018 20:48
вот тут не понял, что после \s может еще присутствовать там между двумя словами?
смысл этого выражения-правило сработает в обоих случаях: 1) между 2 искомыим словами присутствует ещё одно любое слово в связке с пробелом перед ним.
2) между этими двумя искомыми словами только пробел

Аватара пользователя
wasyaka
V.I.P.

Регулярные выражения, что и как

#5

Сообщение wasyaka » 24 июл 2018 22:51

MoppoH писал(а):
24 июл 2018 20:48
чем плохо что используется все предложение, тем что оба слова уже забиты одним рег выражением, и если допустим прилагательное + омограф уже найдено, то это прилагательное уже не пойдет к другому омографу
типа такого, дырявые трубы или печи, заменит только один из омографов
не так поняли:
Увидим кусок берега
#(?i)(?<=(забрызгивала|осмотрел|увидим)[^\.,!?-]{0,30})\bберега\b=берега<
Увидим кусок берегА
И ниже у Вас правило
#(?i)(?<=((вы|у)ступ|глубин|заросли|кусок|обрыв|полоск|приближение)[^\.,!?-]{0,30})\bберега\b=бе<рега
Оно и останится правилом - но не сработает в данном и во многих других случаях...
► Показать
Это чем реги в dic отличаются от rex
В rex сработает последнее самое точное как фильтр грубая-средняя-тонкая очистка...
► Показать

Аватара пользователя
MoppoH
Постоялец

Секреты регулярных выражений

#6

Сообщение MoppoH » 24 июл 2018 23:46

если я правильно понял, dic срабатывает первое в списке рег выражение, а в rex последнее?
просто в этих выражениях не понятно какое из них сработает
#(?i)(?<=((вы|у)ступ|глубин|заросли|кусок|обрыв|полоск|приближение)[^\.,!?-]{0,30})\bберега\b=бе<рега
#(?i)(?<=(забрызгивала|осмотрел|увидим)[^\.,!?-]{0,30})\bберега\b=берега<
если у меня в словаре они идут в таком порядке, то замети на Увидим кусок бе<рега, а второго проигнорирует
KooBAudio_2018-07-24_23-43-11.png
KooBAudio_2018-07-24_23-43-11.png (87.67 КБ) 1787 просмотров

Аватара пользователя
tonio_k
V.I.P.

Секреты регулярных выражений

#7

Сообщение tonio_k » 24 июл 2018 23:54

MoppoH, правила в балаболке в словарях bxd обрабатываются строго по порядку - как записаны в словаре. Последующее правило переписывает результаты срабатывания предыдущего. Правила в формате REX могут чередоваться с DIC в любой комбинации - срабатывание будет по порядку их нахождения в словаре bxd. BXD это новый формат словаря - гибрид. В нем можно заводить строки правил как в формате DIC так и в REX в нужной для пользователя последовательности


Отправлено спустя 34 минуты 16 секунд:
С Максимом удобство в том, что можно одно и то же слово поменять несколько раз разными правилами. А вот с Николаем ситуация немного другая. Изменив в тексте берега на бе<рега слово берегав тексте уже отсутствует. И дальнейшие уточняющие правила уже не могут это слово отловить. Поэтому "последовательная" обработка вам не приемлема. Если вы не перелопатите все свои словари на схему:
берега=бЕрега

А в самом конце уточняющий соварь проставляющий ударения под Николая:
$*бЕ*=бе<
Схема условная в формате dic


Отправлено спустя 7 дней 12 часов 51 минуту 33 секунды:
MoppoH, для себя (пока) нашел такой простой способ поиска вместо ранее используемого мною [^\.,!?-]{0,30} - "примерно" три слова между искомыми словами. Теперь буду пытаться применять (|\w+\s|\w+\s\w+\s|\w+\s\w+\s\w+\s) - т.е. конкретно от 0 до 3 слов
Пример
\bмежду\b\s\b(нами|ними|вами)\b\s(|\w+\s|\w+\s\w+\s|\w+\s\w+\s\w+\s)(\bпропасть\b)=между $1 $2 прОпасть
Сработает на:
Между вами пропасть
Между вами большая пропасть
Между вами самая большая пропасть
Между вами огромная по величине пропасть

Аватара пользователя
wasyaka
V.I.P.

Секреты регулярных выражений

#8

Сообщение wasyaka » 01 авг 2018 15:57

tonio_k писал(а):
01 авг 2018 13:20
(|\w+\s|\w+\s\w+\s|\w+\s\w+\s\w+\s) - т.е. конкретно от 0 до 3 слов
Пример
(| - уже ошибка
((\s(\w+)?){1,})>((\s(\w+)?){1,2})>((\s(\w+)?){1,3}) и т.д.???
tonio_k писал(а):
01 авг 2018 13:20
Если вы не перелопатите все свои словари на схему:
берега=бЕрега
И потом прослезитесь...:cry_baby:
см. картинку
110391...
110392 и т.д

Аватара пользователя
tonio_k
V.I.P.

Секреты регулярных выражений

#9

Сообщение tonio_k » 01 авг 2018 16:27

wasyaka писал(а):
01 авг 2018 15:57
(| - уже ошибка
нет не ошибка. Это как раз тот самый 0 слов между искомыми.
wasyaka писал(а):
01 авг 2018 15:57
((\s(\w+)?){1,})
согласен, но большое количество скобок 2 или 3 в одном создаёт проблему с определением возврата переменной: $4 или $7 надо указать после равно? что бы результаты были не в перемешку? Для меня это вычислять очень сложно - только методом проб и ошибок. А "мой вариант" простой линейный и предсказуемый. Только один вариант вариант в скобках "()". Т.е. $1 или $2 - определить легко, он будет по порядку.

Аватара пользователя
wasyaka
V.I.P.

Секреты регулярных выражений

#10

Сообщение wasyaka » 01 авг 2018 20:02

tonio_k писал(а):
01 авг 2018 16:27
согласен, но
Каждый выбирает по себе...
а MoppoH вообще автор регов для омографов в KooBAudio :thank: ... я лиш ученик и продолжатель в rex :drunkpals:

Аватара пользователя
tonio_k
V.I.P.

Секреты регулярных выражений

#11

Сообщение tonio_k » 02 авг 2018 01:17

Задача - удалить задвоенные пробелы в тексте.
Вопрос, почему результаты разные?

Код: Выделить всё

( ){2,}=$1
(в скобках пробел) -норм отрабатывает

Код: Выделить всё

(\s){2,}=$1
- сбиваются абзацы в один сплошной текст

И еще вопрос: если в регулярных выражениях точка означает пробел, то как это выражение можно записать?

Аватара пользователя
wasyaka
V.I.P.

Секреты регулярных выражений

#12

Сообщение wasyaka » 02 авг 2018 07:18

tonio_k писал(а):
02 авг 2018 01:17
(\s){2,}=$1
- сбиваются абзацы в один сплошной текст
У меня в bxd срабатывает нормально

Аватара пользователя
tonio_k
V.I.P.

Секреты регулярных выражений

#13

Сообщение tonio_k » 02 авг 2018 10:52

wasyaka писал(а):
02 авг 2018 07:18
в bxd
► Показать

Аватара пользователя
wasyaka
V.I.P.

Секреты регулярных выражений

#14

Сообщение wasyaka » 02 авг 2018 13:22

► Показать

Аватара пользователя
tonio_k
V.I.P.

Секреты регулярных выражений

#15

Сообщение tonio_k » 02 авг 2018 13:48

когда это правило одно в словаре т.е. в идеальнх условиях действительно почему-то все корректно.
А вот попробуйте в 1.5. homographs.bxd - в самый конец добавить (\s){2,}=$1 вместо (\s)(\s)=$1 и прогнать текст.

Аватара пользователя
wasyaka
V.I.P.

Секреты регулярных выражений

#16

Сообщение wasyaka » 02 авг 2018 19:56

tonio_k писал(а):
02 авг 2018 13:48
обавить (\s){2,}=$1 вместо (\s)(\s)=$1

А зачем это?
В Балаболке нет "красной" строки - соответственно абзац от абзаца отделяют два пробела которые (\s){2,}=$1 (от двух и до луны :big_smile: ) убираются, соответственно и текст сбивается, из-за этого и (\s)(\s)=$1 - убирается один пробел...
А вообще для этих целей существует форматирование текста в самой проге
► Показать

Аватара пользователя
MoppoH
Постоялец

Секреты регулярных выражений

#17

Сообщение MoppoH » 04 авг 2018 20:23

tonio_k писал(а):
01 авг 2018 13:20
Пример
\bмежду\b\s\b(нами|ними|вами)\b\s(|\w+\s|\w+\s\w+\s|\w+\s\w+\s\w+\s)(\bпропасть\b)=между $1 $2 прОпасть
Сработает на:
Между вами пропасть
Между вами большая пропасть
Между вами самая большая пропасть
Между вами огромная по величине пропасть
очень понравилась такая идея не искать количество символов возле слова, а искать именно число слов возле слова, как мне кажется так поиск идет более четко, вот у меня получилось такое выражение
#(?i)\bзадвигал\b(?=\s(\w+\s){0,4}[^\.,!?-]?(ящик))=задвигАл
ищет от 0 до 4 слов после слова задвигал и если нет знаков препинания

Аватара пользователя
tonio_k
V.I.P.

Секреты регулярных выражений

#18

Сообщение tonio_k » 05 авг 2018 00:34

MoppoH, везет вам - не требуется указывать $1 $2...$7 после равно :big_smile:
попробовал ваш пример подогнать под Демагог/Балалболку.
Задвигал за ширму ящик Первый сюрприз - вот совсем не $1 после равенства, хотя казалось бы есть общая скобка и вроде бы она должна быть первой:
\bзадвигал\b(?=\s(\w+\s){0,4}[^\.,!?-]?(ящик))=задвигАл $3
добавляю в текст запятую (а тут убираю: [^\.!?-])- все равно не срабатывает во всех случаях при наличии запятой в тексте
MoppoH писал(а):
04 авг 2018 20:23
если нет знаков препинания
\bзадвигал\b(?=\s(\w+\s){0,4}[^\.,!?-]?(ящик))=задвигАл а разве выделеный участок как раз и не предполагает отсутствие какого либо знака препинания? Это же слово и сразу пробел после него. А [^\.,!?-] - подразумевает отсутствие знака препинания только перед словом ящик. Хотя обязательный пробел после \w - так же и запрещает знак препинания?

Предыдущий пример:
\bмежду\b\s\b(нами|ними|вами)\b\s(|\w+\s|\w+\s\w+\s|\w+\s\w+\s\w+\s)(\bпропасть\b)=между $1 $2 прОпасть
Немного сократил:
\bмежду\b\s\b(нами|ними|вами)\b\s(|\w*\s*\w*\s*\w*\s*)(\bпропасть\b)=между $1 $2 прОпасть
То же но с учетом наличия в тексте запятой:
\bмежду\b\s\b(нами|ними|вами)\b\s(|\w*\,*\s*\w*\,*\s*\w*\,*\s*)(\bпропасть\b)=между $1 $2 прОпасть

Аватара пользователя
MoppoH
Постоялец

Секреты регулярных выражений

#19

Сообщение MoppoH » 05 авг 2018 11:56

tonio_k писал(а):
05 авг 2018 00:34
\bзадвигал\b(?=\s(\w+\s){0,4}[^\.,!?-]?(ящик))=задвигАл а разве выделеный участок как раз и не предполагает отсутствие какого либо знака препинания?
не знаю как в других читалках работают рег выражения напишу как в кубаудио это ищет
\bзадвигал\b ищет целиком слово в тексте
(?=\s эта часть показывает что между словом что ищет и другим есть пробел
(\w+\s) показывает что надо найти слово с пробелом
{0,4} показывает что слов с пробелом должно быть от 0 до 4
[^\.,!?-]? это определяет что между этими словами от 0 до 4 не должно быть знаков препинания
(ящик)) означает какое слово должно быть в связке с искомым омографом

не знаю как точно должно работать оно у вас но типа такого должно сработать
\bзадвигал\b(\s(\w+\s){0,4}[^\.,!?-]?)(сундук|чемодан|ящик)=задвигАл $1 $+

Аватара пользователя
tonio_k
V.I.P.

Секреты регулярных выражений

#20

Сообщение tonio_k » 06 авг 2018 10:36

MoppoH писал(а):
05 авг 2018 11:56
[^\.,!?-]? это определяет что между этими словами от 0 до 4 не должно быть знаков препинания
мне видется, что этот запрет в правиле лишний. Т.е. от него нет смысла. У вас в правиле ищется от 0 до 4 связка: "словопробел" эта связка сама по себе будет игнорировать связку "словозапятаяпробел". Другое дело, что без [^\.,!?-] само правило по каким то технически причинам не работает - типа обязательно аргумента.

Аватара пользователя
wasyaka
V.I.P.

Секреты регулярных выражений

#21

Сообщение wasyaka » 07 авг 2018 10:46

tonio_k писал(а):
06 авг 2018 10:36
Другое дело, что без [^\.,!?-] само правило по каким то технически причинам не работает
► Показать

Код: Выделить всё

(\w+(|)\b\s?(\w+)?)\s{1,4}(\b\b)=$1 
(\b(|)(\w+)?(\s(\w+)?){1,})(\b\b)=$1 
(\b(|)(\w+)?\s?(\w+)?)\s{1,4}\b(и|или|с)\b\s{1,4}(\b\b)=$1 $5 
(\b(|)\b\s?(\w+)?)\s{1,4}\b(и|или|с)\b\s{1,4}(\b\b)=$1 $4 
(\b(|)\b\s?(\w+)?)\s{1,4}(\b\b)=$1 
\b(|)\b\s{1,4}(\b\b)=$1 

(\b\b)(\s?(\w+)?\s{1,4}(\w+(|)\b))= $2
(\b\b)((\s(\w+)?){1,}(|)(\w+)?)= $2
(\b\b)\s{1,4}\b(и|или|с)\b(\s?(\w+)?\s{1,4}\b(|)\b)= $2 $3
(\b\b)(\s?(\w+)?\s{1,4}\b(|)\b)= $2
(\b\b)\s{1,4}\b(|)\b= $2
(\b\,)\s{1,4}\b(|)\b=, $2

\b(|)\b\s{1,4}(\b\b)\s{1,4}\b(|)\b=$1 XXX $3
@(\b\b)\s{1,4}\b([А-ЯЁ]\w+)\b= $2
@(\b\b)\s{1,4}\b([А-ЯЁ](\w+)?)= $2
(\…|\.|\,|\!|\?|\:|\;|\-)\s(\b\b)(\…|\.|\,|\!|\?|\:|\;|\ -)=$1 ххх$3



Отправлено спустя 10 часов 25 минут 18 секунд:
wasyaka писал(а):
07 авг 2018 10:46
(\b\b)
омограф в скобках для общей унификации и предотвращения путаницы с $

Код: Выделить всё

(\w+(|)\b\s?(\w+)?)\s{1,4}\b(авиа|мех)?(корпуса\b)=$1 $4корпусА
(\b(|)(\w+)?(\s(\w+)?){1,})\b(авиа|мех)?(корпуса\b)=$1 $6кОрпуса
(\b(|)\b\s?(\w+)?)\s{1,4}\b(и|или|с)\b\s{1,4}\b(авиа|мех)?(корпуса\b)=$1 $4 $5корпусА
\b(|)\b\s{1,4}\b(авиа|мех)?(корпуса\b)=$1 $2корпусА
\b(авиа|мех)?(корпуса\b)(\s?(\w+)?\s{1,4}(\w+(|)\b))=$1кОрпуса $3
\b(авиа|мех)?(корпуса\b)((\s(\w+)?){1,}(|)(\w+)?)=$1корпусА $3
\b(авиа|мех)?(корпуса\b)\s{1,4}\b(|)\b=$1корпусА $3
\b(авиа|мех)?(корпуса\b)=$1$2
Для многих пар омографов (редких) шаблоны работают практически без ошибочно, а для часто встречаемых - индувидуальный подход...
Это как Восток - :big_smile: дело тонкое

Аватара пользователя
tonio_k
V.I.P.

Секреты регулярных выражений

#22

Сообщение tonio_k » 12 окт 2018 00:47

Пример правила:
\bвсё\b=всЪё
\bвсЪё\b=всё

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


Отправлено спустя 6 минут 25 секунд:
Туплю на ночь глядя :facepalm: Каждый вариант прописать через @ (учёт регистра) и всего делов. Но может есть какое то написание, что бы в одну строку прописать?

Аватара пользователя
Arex
Интересующийся

Секреты регулярных выражений

#23

Сообщение Arex » 14 окт 2018 09:52

tonio_k писал(а):
02 авг 2018 01:17
(\s){2,}=$1
- сбиваются абзацы в один сплошной текст
В это множество входят не только пробелы, но и табуляции, и переносы строк (\r и \n), так что не удивительно.
tonio_k писал(а):
12 окт 2018 00:53
Вопрос, как прописать, что бы на выходе было слово всё но с таким же регистром букв, как первоначально
Не очень понимаю, зачем нужна замена, которая не меняет ничего?

Аватара пользователя
tonio_k
V.I.P.

Секреты регулярных выражений

#24

Сообщение tonio_k » 14 окт 2018 10:45

Arex писал(а):
14 окт 2018 09:52
Не очень понимаю, зачем нужна замена, которая не меняет ничего?
вот тут смысл приводится: https://www.mytts.info/viewtopic.php?p=153#p153

Аватара пользователя
Arex
Интересующийся

Секреты регулярных выражений

#25

Сообщение Arex » 14 окт 2018 11:21

Понятно.
Тогда в начале

Код: Выделить всё

\b(всё)\b=$1Ъ
а в конце

Код: Выделить всё

\b(всё)Ъ\b=$1
Так регистр сохранится.

Если же хочется именно "всЪё", можно так

Код: Выделить всё

\b(вс)(ё)\b=$1Ъ$2
\b(вс)Ъ(ё)\b=$1$2

Ответить

Вернуться в «Разное»