Попытка проверить, содержит ли строка заданное слово

function msgcontains(msg, what)
    msg = msg:lower()

    -- Should be replaced by a more complete parser
    if type(what) == "string" and string.find(what, "|", 1, true) ~= nil then
        what = what:explode("|")
    end

    -- Check recursively if what is a table
    if type(what) == "table" then
        for _, v in ipairs(what) do
            if msgcontains(msg, v) then
                return true
            end
        end
        return false
    end

    what = string.gsub(what, "[%%%^%$%(%)%.%[%]%*%+%-%?]", function(s) return "%" .. s end)
    return string.match(msg, what) ~= nil
end

Эта функция используется на RPG-сервере, в основном я пытаюсь соответствовать тому, что говорит игрок.

например; если msgcontains(msg, "привет"), то

msg = сообщение, которое отправил игрок

Тем не менее, он соответствует чему-то вроде «yesimstupidпривет», он действительно не должен соответствовать, потому что «привет» — это не одно слово, есть идеи, что я могу сделать? Т_Т


person Raúl Sanpedro    schedule 17.07.2015    source источник
comment
Попробуйте return string.match(' '..msg..' ', '%W'..what..'%W') ~= nil   -  person Egor Skriptunoff    schedule 18.07.2015


Ответы (3)


Вы можете использовать трюк, упомянутый Егором в его комментарии, а именно: добавить некоторые символы, не являющиеся словами, во входную строку, а затем заключить регулярное выражение с небуквенным %A (или не буквенно-цифровым с %W, если вы хотите также запретить цифры ).

Итак, используйте

return string.match(' '..msg..' ', '%A'..what..'%A') ~= nil

or

return string.match(' '..msg..' ', '%W'..what..'%W') ~= nil

Этот код:

--This will print "yes im stupid hi" since "yes" is a whole word
msg = "yes im stupid hi"
if msgcontains(msg, "yes") then
    print(msg)
end
--This will not print anything
msg = "yesim stupid hi"
if msgcontains(msg, "yes") then
    print(msg)
end

Вот демонстрация CodingGround

person Wiktor Stribiżew    schedule 17.07.2015

Границы хороши для работы с границами шаблона (см. поиск слова)), и вам не нужно будет изменять строку:

return msg:match('%f[%a]'..what..'%f[%A]') ~= nil

Граница '%f[%a]' соответствует, только если предыдущий символ не был в '%a', а следующий есть. Шаблон Frontier доступен с версии 5.1, а официальный с версии 5.2.

person ryanpattison    schedule 18.07.2015
comment
Конечно! %f доступен в версии 5.1.5! - person Egor Skriptunoff; 18.07.2015

Просто подумайте о том, "что такое слово". Слово имеет определенные символы впереди и позади него, такие как пробелы (пробел, табулятор, новая строка, возврат каретки,...) или пунктуация (запятая, точка с запятой, точка, линия,...). Кроме того, слово может быть в начале или в конце текста.

%s, %p, ^ и $ должны вас заинтересовать.

Подробнее см. здесь.

person Youka    schedule 17.07.2015