Гайд Введение в регулярные выражения за 15 минут.

Перед началом прочтения данной статьи ознакомьтесь с
  1. http://umodel.narod.ru/webhelp/ams/Program_Reference/Actions/RegExp_Lua.htm
  2. https://user.su/lua/index.php?id=9
Если после прочтения всего этого вы так ничего не поняли, то это печально.
Попытаюсь максимально подробно расписать базовые варианты, которые надо людям в 99% случаях. Остальные варианты подставить самим вам уже не составит после прочтению этой статьи (надеюсь).

Для начала рассмотрим методы find и match.
find -
возвращает позицию подстроки в строке. Принимает 4 параметра. Мы же будем использовать только 2: строку в которой будет искать, и шаблон который будем искать.
match - ищет первое вхождение шаблона в строку, возвращая захваченные значения. Принимает 3 параметра. Мы же будем использовать только 2: строку в которой будет искать, и шаблон который будем искать.

Рассмотрим первый банальный пример, который я придумал только что.
Lua:
text = 'Привет Сеня, меня зовут Дима, мне 18 лет, а тебе сколько?' -- строка которую мы будем обрабатывать
Давайте достанем отсюда Имя второго собеседника, и возраст.
Lua:
text = 'Привет Сеня, меня зовут Дима, мне 18 лет, а тебе сколько?' -- строка которую мы будем обрабатывать
if string.find(text--[[строка в которой ищем текст]], 'Привет (.-), меня зовут .-, мне (%d+) лет, а тебе сколько?'--[[шаблон который надо искать]]) then
end
Какие точки с минусами я натолкал. Давайте разберем. После прочтения текста в ссылках в начале темы вы уже могли догадаться что это и есть те самые регулярные выражения.
. (точка) соответствует любому символу.
+ (плюс) соответствует неограниченному повторению. Эти символы будут всегда соответствовать самой длинной возможной последовательности.
- (минус) соответствует неограниченному повторению. Эти символы будут всегда соответствовать самой короткой возможной последовательности. Т.е например после пробела оно уже не будет работать. Рассмотрим чуть позже это.
%d соответствует любой цифре.
Если регулярные выражения в находятся в скобках, это значит что match их захватит и мы сможем их поместить в переменную.
Возвращаемся к нашему примеру. Мы ему указали что нам надо захватить самую короткую возможную последовательность после слова "Привет". дальше мы указали что в строке присутствует еще текст после слова "зовут", но поскольку он не находится в скобках - метод match его не захватит. Дальше мы указываем что в строке после слова "мне" есть какое то число. Поскольку выражение находится в скобках - match его захватит.
Lua:
text = 'Привет Сеня, меня зовут Дима, мне 18 лет, а тебе сколько?' -- строка которую мы будем обрабатывать

if string.find(text--[[строка в которой ищем текст]], 'Привет (.-), меня зовут .-, мне (%d+) лет, а тебе сколько?'--[[шаблон который надо искать]]) then
    name, age --[[указываем переменные в которые нужно поместить текст]]= string.match(text--[[строка в которой ищем текст]], 'Привет (.-), меня зовут .-, мне (%d+) лет, а тебе сколько?'--[[шаблон который надо искать]])
    print(name, age) -- Выводим содержимое переменных. Т.е данный код выведет "Сеня    18"
end

Давайте рассмотрим отличия .+ и .-.
Представим что в каком то хуке в переменную text нам прилетело сообщение
Lua:
text = 'Продам коня с бронзовым копытом. Цена договорная'
Поставим .+ т.е самую длинную возможную последовательность.
Lua:
text = 'Продам коня с бронзовым копытом. Цена договорная'
if string.find(text, 'Продам (.+)') then
    var = string.match(text, 'Продам (.+)')
    print(var)
end
Lua:
--output << коня с бронзовым копытом. Цена договорная
Поставим .- т.е самую короткую возможную последовательность
Lua:
text = 'Продам коня с бронзовым копытом. Цена договорная'
if string.find(text, 'Продам (.-)') then
    var = string.match(text, 'Продам (.-) ')
    print(var)
end
Lua:
--output << коня
Думаю понятно. Ничего сложного в этом нет.

Волшебные символы​

В регулярных выражениях луа присутствуют волшебные символы, а именно ^$()%.[]*+-?
В своем коде вам нужно их экранировать. Экранирование осуществляется при помощи символа %.
Рассмотрим пример.
Lua:
text = '[Сантехник] Николай говорит: куплю коня.'
Представим что нам нужно узнать профессию, имя и то, что человек говорит. Если мы сделаем так как делали чуточку выше, а именно
Неправильный вариант:
text = '[Сантехник] Николай говорит: куплю коня.'
if string.find(text, '[(.-)] (.-) говорит: (.+)') then
    profession, name, msg = string.match(text, '[(.-)] (.-) говорит: (.+)')
    print(profession, name, msg)
end
То у нас ничего не сработает по 1 понятной причине, а именно из-за [] которые относятся к волшебным символам, а их, в свою очередь, нужно экранировать. Посмотрим на правильный вариант:
Правильный вариант:
text = '[Сантехник] Николай говорит: куплю коня.'
if string.find(text, '%[(.-)%] (.-) говорит: (.+)') then
    profession, name, msg = string.match(text, '%[(.-)%] (.-) говорит: (.+)')
    print(profession, name, msg)
end
Lua:
--output << Сантехник Николай куплю коня.

Важно: внимательные уже заметили, что знак экранирования(процент (%)) тоже относится к волшебным символам, и экранируется он особенно, а именно двумя процентами. Можно и одним, но если у вас возникнут проблемы - будете виноваты сами, потому что я не помню зачем там 2 процента, но помню что надо :D. Для примера возьмем
Lua:
text = 'Процентная ставка составляет 3%!'
И вытащим отсюда процентную ставку в процентах.
Lua:
text = 'Процентная ставка составляет 3%!'
if string.find(text, 'Процентная ставка составляет (%d+)%%%!') then
    rate = string.match(text, 'Процентная ставка составляет (%d+)%%%!')
    print(rate)
end
Lua:
--output << 3

Упрощаем код.​

Выше я использовал string.find и string.match, но эти методы можно использовать напрямую. Тут на самом деле нечего расписывать, я попросту пример про сантехника который наводил чуть выше, и покажу как его можно оформить этим способом.
Lua:
text = '[Сантехник] Николай говорит: куплю коня.'
if text:find('%[(.-)%] (.-) говорит: (.+)') then -- мы избавились от первого аргумента, так как применяем функцию к конкретной переменной, в нашем случае к переменной text
    profession, name, msg = text:match('%[(.-)%] (.-) говорит: (.+)') -- аналогичная ситуация
    print(profession, name, msg)
end

Примерчики на счет цифр и чисел.​

Возьмем следующий код, а именно получим число
Lua:
text = 'Сходил я в этот ваш барбершоп, правда не понял за что 3000 отдал.'
if text:find('(%d+)') then
    print(text:match('(%d+)'))
end

--output << 3000
Возьмем этот же пример, но уберем +, и на выходе получим первую цифру
Lua:
text = 'Сходил я в этот ваш барбершоп, правда не понял за что 3000 отдал.'
if text:find('(%d)') then
    print(text:match('(%d)'))
end

--output << 3
Получим все, кроме цифр (до первой цифры) из строки:
Lua:
text = 'Сходил я в этот ваш барбершоп, правда не понял за что 3000 отдал.'
if text:find('(%D+)') then
    print(text:match('(%D+)'))
end

--output << Сходил я в этот ваш барбершоп, правда не понял за что

Оптимизация сценария.​

Возьмем тот же пример с сантехником. Использование и find и match там не обязательно, ведь мы же знаем что будем получать аргументы, зачем нам финд? Рассмотрим оптимизированный вариант:
Lua:
text = '[Сантехник] Николай говорит: куплю коня.'
profession, name, msg = text:match('%[(.-)%] (.-) говорит: (.+)')
if profession and name and msg then
    print(profession, name, msg)
end
В коде выше мы распределяем текст по аргументам, а потом проверяем их на nil. Т.е если нужный нам текст не появился - ничего не произойдет, так как содержимое переменных будет nil, ну а как только появился - выполнится код.
Вроде бы все объяснил и упомянул. Если что-то забыл - напишите об этом ниже.
 
Последнее редактирование:

darksoor

Известный
674
353
Зачем сначала делать find потом еще раз делать тот же find, но уже с возвратом аргументов(match)
Не проще матчить и проверять прошел ли вообще матч?
Тут всё зависит мне кажется от удобства. Если тебе нужно сразу найти строку, а после уже получить аргументы, то тогда не проще.
Эх, а в AHK есть if RegExMatch(), куда проще с ним работать.
 

AnWu

Guardian of Order
Всефорумный модератор
4,687
5,166
Тут всё зависит мне кажется от удобства. Если тебе нужно сразу найти строку, а после уже получить аргументы, то тогда не проще.
Эх, а в AHK есть if RegExMatch(), куда проще с ним работать.
он прав. оптимизация, чел. если ты знаешь что при нахождении нужны результаты - используй матч
 

sᴀxᴏɴ

#Mary
Всефорумный модератор
791
846
Зачем сначала делать find потом еще раз делать тот же find, но уже с возвратом аргументов(match)
Не проще матчить и проверять прошел ли вообще матч?
тоже интересно стало
1625869244982.png
 
  • Ха-ха
Реакции: kin4stat

Fott

Простреленный
Автор темы
3,430
2,265
он прав. оптимизация, чел. если ты знаешь что при нахождении нужны результаты - используй матч
Зачем сначала делать find потом еще раз делать тот же find, но уже с возвратом аргументов(match)
Не проще матчить и проверять прошел ли вообще матч?
В первую очередь это было сделано чтобы наглядно показать что за что отвечает. Добавил использование исключительно match.