Исходник Информация Гайд AHK RegExMatch | SAMP | Пишем свой авто-ответчик

Тема в разделе "AutoHotKey", создана пользователем BASS_DEVSOFTWARE, 17 мар 2019.

  1. BASS_DEVSOFTWARE

    BASS_DEVSOFTWARE vk.com/bass_devware
    Проверенный

    Регистрация:
    29 апр 2017
    Сообщения:
    151
    Симпатии:
    113
    Приветствую всех! :bye:

    Данная статья должна помочь разобраться новичкам в Регулярных выражениях и помочь им самостоятельно писать скрипты на автоматический ответ, при появлении в чате N-строки (по задумке).


    :help::help::help:


    Перед игроком появляется будто бы непреодолимая стена, посмотрев на которую, он побежит по форумам просить помощи.

    :help::help::help:



    [​IMG]


    Хочу предупредить - данная статья рассчитана на незнающих пользователей. Поэтому подробность данной статьи - это скорее плюс (как по мне).



    Для начала, предлагаю взять каркас нашего скрипта:​
    
    #Include samp.ahk
    #IfWinActive GTA:SA:MP
    
    ChatLog = C:\Users\User\Documents\GTA San Andreas User Files\SAMP\chatlog.txt
    
    loop
    {
    lastline := GetNewLine(ChatLog)
    ;Здесь будет наше регулярное выражение
    If expression !=
    {
       SendChat("команда")
    }
    }
    
    GetNewLine(filename)
    {
    static old
    static new
    if !old
        {
            FileGetSize, old, %filename%
            new := old
        }
    while old = new
        {
            sleep 100 ;задержка
            FileGetSize, new, %filename%
        }
    old := new
    Loop, read, %filename%
    if A_LoopReadLine
        {
            last := A_LoopReadLine
        }
    return last
    }
    
    !end::ExitApp
    end::Reload
    
    Примечание: Для работы вам потребуется скачать AutoHotKey и SAMP UDF.




    Что же мы имеем в нашем каркасе? Давайте разберёмся:
    
    ;Строка # 1 отвечает за загрузку библиотеки SAMP UDF (обязательно действие при написании скриптов с использованием UDF)
    ;Строка # 2 исполняет скрипт только в открытом приложении GTA
    #Include samp.ahk
    #IfWinActive GTA:SA:MP
    
    ;Путь к chatlog.txt, а именно к файлу, где сохраняются все сообщения из чата игры
    ChatLog = C:\Users\User\Documents\GTA San Andreas User Files\SAMP\chatlog.txt
    
    
    ; Начало нашего цикла
    loop
    {
    
    
    ; lastline - переменная, что хранит в себе данные, полученные с функции GetNewLine.
    lastline := GetNewLine(ChatLog)
    
    
    ;Здесь будет наше регулярное выражение и этим всё сказано (вернёмся позже).
    
    
    ;Условие, которое будет исполнено при НЕ пустой переменной регулярного выражения.
    If expression !=
    {
    
    
    ;SendChat - функция, которая позволяет писать в чат не используя клавиатуру и базовые возможности АХК. (Send, SendInput, SendRaw и.т.д.)
    SendChat("команда")
    
    
    ; 1. Закрыли условие expression
    ; 2. Закрыли цикл loop
    }
    }
    
    
    ; Далее идёт функция, что определяет появившуюся строку в чате.
    ; На данном этапе не вижу смысла разбирать эту функцию построчно,
    ; но в будущем, при потребности - мы обязательно это сделаем.
    
    GetNewLine(filename)
    {
    static old
    static new
    if !old
        {
            FileGetSize, old, %filename%
            new := old
        }
    while old = new
        {
            sleep 100
            FileGetSize, new, %filename%
        }
    old := new
    Loop, read, %filename%
    if A_LoopReadLine
        {
            last := A_LoopReadLine
        }
    return last
    }
    
    
    ; Строка № 1 - Сочетание клавиш Alt+END - завершит процесс данного скрипта
    ; Строка № 2 - Нажатие END - перезагрузит скрипт, после чего он будет готов к работе
    !end::ExitApp
    end::Reload
    




    Надеюсь, вы поняли структуру и что за чем идёт.
    Теперь смело копируйте каркас нашего скрипта, чтобы мы смогли вместе его редактировать.
    (Копируйте цельным блоком, что я предоставил вам в самом начале)

    И вот мы подошли к моменту, на котором желторотики вскрывают себе вены, а новички бьются в конвульсиях, я говорю о РеГуЛяРнЫх ВыРаЖеНиЯх.

    Я не собираюсь копировать термин из Википедии, что такое "Регулярные выражения". Скажу своими словами: Регулярные выражения - это возможность копировать/вырезать/отправлять, одним словом - обработать необходимую нам строку и достать из неё N-слова. Будь они статичны или переменны - роли не играет.​

    :hunter:Строку, что нам нужна, будем определять благодаря этим же Регулярным выражениям.:hunter:
    В нашем случае - мы будем рассматривать строки такого типа:​




    Ну что, включаем мозг?



    В Регулярных выражениях есть такое понятие, как литеральный текст. Звучит страшно, но расскажу максимально понятно и только то, что нужно.

    \
    .
    *
    ?
    +
    [
    {
    |
    (
    )
    ^
    $

    Если в искомой строке есть/могут быть литеральные символы, необходимо - нет, не плакать.
    Перед и После литеральный символ необходимо обставить \Q и \E соответственно.
    Таким образом, например " [ ", будет считаться не буквально и будет воспринято как часть строки.
    
    ; Строка в стандартном виде
    Nick_Name[7]
    ; Строка в виде регулярного выражения
    Nick_Name\Q[\E7\Q]\E
    ; Или же
    Nick_Name\[7\]
    
    Поправка: \Q .. \E в написании, можно заменить на \ перед любым литеральным символом.
    Пример выше.

    Главное - не забыть о существовании литеральных символов в принципе.
    Запомнили? Молодцы.

    Так же, Регулярное выражение не прощает опечаток!
    Лишний пробел или его отсутствие может запороть любую "регулярку". И уж поверьте - одним криком от отчаяния и злости от глупого прокола вы не обойдётесь.
    Поэтому, всегда следите при написании Регулярного выражения за тем, чтобы они были 1 в 1: "регулярка" в своём понимании, а наша строка - в своём.
    
    ;Пример № 1, правильно составленное регулярное выражение:
    var = ert tre zsdf
    RegExMatch(var, "ert t(.)e zsdf", var)
    MsgBox % var1
    
    ;Пример № 2, НЕправильно составленное регулярное выражение:
    var = ert tre zsdf
    RegExMatch(var, "ert t(.)e  zsdf", var)
    MsgBox % var1
    
    ;Ошибка примера № 2, в виде лишнего пробела перед zsdf.
    ;Не допускайте таких ошибок.
    
    Структура Регулярного выражения до боли проста:
    
    RegExMatch(ПеременнаяОтСюдаЧитаем, "Опции искомой строки", результат на выходе)
    


    [​IMG]



    Плавно подошли к написанию собственного Регулярного выражения.

    Возьмём за пример эту строку:​
    Из неё нам необходимо "вытащить" Фамилию, ID и само сообщение. Приступим?
    
    ;Для примера нам необходимо создать переменную var, в которой будет находиться наша строка.
    var = [16:24:44] Nick_Name[7]: по чём штаны?
    
    
    ;Опустим нашу переменную, теперь занимаемся только строкой ниже:
    RegExMatch(var, "[16:24:44] Nick_Name[7]: по чём штаны?", find)
    ;Нам нужно достать: Фамилию, ID и сообщение.
    
    Выражение (.*), иногда называют ВсёЧтоУгодно, оно позволит скопировать необходимые нам части сообщения.​
    
    RegExMatch(var, "[16:24:44] Nick_(.*)[(.*)]: (.*)", find)
    
    Теперь занимаемся литеральными символами. У нас их 4.
    Две [ скобочки и две ] скобки.​
    
    RegExMatch(var, "\Q[\E16:24:44\Q]\E Nick_(.*)\Q[\E(.*)\Q]\E: (.*)", find)
    
    Так как наша строка будет читаться из чатлога, время из [16:24:44] и при необходимости Nick_ будут переменны. Поэтому добавляем выражение и для них:​
    
    RegExMatch(var, "\Q[\E(.*):(.*):(.*)\Q]\E (.*)_(.*)\Q[\E(.*)\Q]\E: (.*)", find)
    
    Что мы имеет на выходе?
    Строка, что будет подходить под параметры нашего Регулярного выражения, будет читаться.
    И переменная " find " обретёт содержимое.
    Хочу добавить примеры строк, что могут и будут определены:​
    Теперь немного о переменной find.
    Как вы помните, выражение (.*) позволяет не только пропускать N-слова в строчке под условие,
    но и определять их для дальнейшего использования.
    В данном выражении у нас есть 7 элементов​
    RegExMatch(var, "\Q[\E(.*):(.*):(.*)\Q]\E (.*)_(.*)\Q[\E(.*)\Q]\E: (.*)", find)
    Для того, чтобы использовать каждый элемент для своих нужд, необходимо слитно с переменной find записать порядковый номер элемента (.*)​
    
    ;[16:24:44] Nick_Name[7]: по чём штаны?
    ;RegExMatch(var, "\Q[\E(.*):(.*):(.*)\Q]\E (.*)_(.*)\Q[\E(.*)\Q]\E: (.*)", find)
    msgbox % find5 ; покажет нам Name
    msgbox % find7 ; покажет нам сообщение
    msgbox % find6 ; покажет нам ID
    


    Используем наше выражение​



    Вот мы и составили наше Регулярное выражение. Теперь вставляем его в пример ниже:​
    
    #Include samp.ahk
    #IfWinActive GTA:SA:MP
    
    ChatLog = C:\Users\User\Documents\GTA San Andreas User Files\SAMP\chatlog.txt
    
    loop
    {
    lastline := GetNewLine(ChatLog)
    RegExMatch(var, "\Q[\E(.*):(.*):(.*)\Q]\E (.*)_(.*)\Q[\E(.*)\Q]\E: (.*)", find)
    
    If find6 !=
    {
       SendChat("команда")
    }
    }
    
    GetNewLine(filename)
    {
    static old
    static new
    if !old
        {
            FileGetSize, old, %filename%
            new := old
        }
    while old = new
        {
            sleep 100 ;задержка
            FileGetSize, new, %filename%
        }
    old := new
    Loop, read, %filename%
    if A_LoopReadLine
        {
            last := A_LoopReadLine
        }
    return last
    }
    
    !end::ExitApp
    end::Reload
    
    Если элемент "ID" не будет пуст, в чат будет отправлено сообщение "команда".
    Дальше уже можно по своему вкусу изменять данное условие. Приведу лишь пару примеров:​
    
    If find6 !=
    {
       SendChat("/mute " find6 " 30 флуд")
    }
    ; Если элемент "ID" не будет пуст, в чат от вас последует команда /mute id 30 флуд, что выдаст мут по данному ID
    
    
    If find5 !=
    {
       SendChat("Адмирал " find5 " , что вы хотели этим сказать?")
    }
    ;В чат будет отправлено сообщение: Адмирал Name, что вы хотели этим сказать?
    
    
    If find7 !=
    {
       SendChat("Цитирую: " find7)
    }
    ;В чат будет отправлено сообщение: Цитирую: по чём штаны?
    
    На этом тема данной статьи подошла к концу.
    Используйте данный пример, составляйте свои "регулярки" и будьте всегда первыми в конкурсе "Решите пример: 557 + 992"​


    Немного о функции SendChat
    Для отправки сообщения, необходимо его закрыть в "", чтобы получилось так:​
    
       SendChat("Адмирал")
    
    Чтобы в строке читалась переменная, необходимо закрыть открытую " и вписать имя переменной, не используя %%, так как в этом случае значение переменной будет читаться так же, как переменная.
    
       SendChat("Адмирал" var)
    

    Немного о функции addChatMessage
    addChatMessage позволяет отправлять в чат фэйк-сообщения, которые видите только вы.
    Это можно использовать для того, чтобы при запуске скрипта - в чат было отправлено сообщение о запуске, при любом действии, и т.д.​
    
     addChatMessage("Сообщение")
    ; Самое стандартное сообщение
    
    Чтобы изменить цвет сообщения, необходимо добавить HTML коды цветов:
    
    addChatMessage("{FF8C00} bass_devware")
    




    Подведём итоги

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


    Любые вопросы можете задавать в данной теме и просьба БЛАГОДАРИТЬ тех, кто вам поможет своим ответом.
    Светлого будущего и удачи!
    Спасибо, что дочитали до конца.





    [​IMG]

     
    #1 BASS_DEVSOFTWARE, 17 мар 2019
    Последнее редактирование: 18 мар 2019
    FkeTe, livingflore, Cod и 10 другим нравится это.
  2. Belo4ka_belka

    Belo4ka_belka Интересующийся

    Регистрация:
    28 июл 2015
    Сообщения:
    120
    Симпатии:
    2
    А зачем такие сложности с \Q \E? Можно \[ использовать и тоже будет все воспринято буквально. Ещё совету уточнить что .* означает не просто ВсеЧтоУгодно а и пустоту ибо обычно в голове всплывает наличие чего-либо но никто не додумается что под этот термин попадет и отсутствие.
     
  3. BASS_DEVSOFTWARE

    BASS_DEVSOFTWARE vk.com/bass_devware
    Проверенный

    Регистрация:
    29 апр 2017
    Сообщения:
    151
    Симпатии:
    113
    Мешает желание пользователя.
    Данная тема демонстрирует альтернативу с использованием autohotkey.

    1. Допишу в виде нюанса. Но для начала лучше использовать через \Q, для лучшего понимания структуры Регулярного выражения.
    2. ВсёЧтоУгодно - символ, слово, предложение, включает в себя и ничего.
     
    Proganet нравится это.
  4. Belo4ka_belka

    Belo4ka_belka Интересующийся

    Регистрация:
    28 июл 2015
    Сообщения:
    120
    Симпатии:
    2
    1. Не знаю есть ли смысл понимания структуры если ты в сампике применяешь. Банальный пример это тот самый .* который является самым нерекомендованным шаблоном из всех (ввиду своего значения), но в сампике все легко проходит за счёт пробелов (многие даже ни разу с жадностью не сталкивались потому что пробелы на серверах очень сейвят от этого). Ты же не собираешься html шаблоны разбирать потому \и стоит рассматривать как основной вариант (который даже в html кстати зайдет нормально).
    2. Не спорю, только это очень неочевидная вещь. Ты же пишешь статью тем, кто только умеет создавать на форуме "помогите сделать скрипт который удерживает кнопку". Уверен что 90 процентов целевой аудитории твоей статьи даже не смогут определить примерное место возникновения ошибки времени исполнения. Лучше уточнить в общем).
     
    BASS_DEVSOFTWARE нравится это.
  5. Cod

    Cod Активный участник

    Регистрация:
    18 янв 2018
    Сообщения:
    44
    Симпатии:
    4
    Да, для новичков именно как святой Грааль эта тема. Годно
     
    BASS_DEVSOFTWARE нравится это.