(repost: https://stackoverflow.com/questions/59665338/censoring-words-in-lua#comment105491094_59665338, as advised)

Im currently making a discord censor bot for my friend, and I was wondering if anyone with experience could help me, or if theres an easier way to complete my code.

local BadWords = {

client:on('messageCreate', function(msg)
    Msg = msg.content
    local msgs = string.split(Msg,' ')
    for i,v in pairs(msgs) do
        if BadWords[v:lower()] then
                embed = {
                    fields = {
                    {name = "Bad Word",value=v,inline = true},
                    color = discordia.Color.fromRGB(114, 137, 218).value,

                    --footer = os.time(),
            --msg:reply(('Blacklisted word: %s'):format(v))
        if BadWords[i] or BadWords[v] then
            msg:reply(('Blacklisted word: %s'):format(v))

There's nothing wrong with it, nor is it complete but my idea was to split, or concatenate all the words they send respectively, mutate into all versions of the word (i.e. farm, f4rm, type shit) and then checking the BadWord list.

Mostly what I was wondering was if there's a more efficient way to do this, or if I just gotta do what I gotta do

  • \$\begingroup\$ This won't catch words like poop, and several others. \$\endgroup\$ Jan 9, 2020 at 16:25
  • \$\begingroup\$ It works, I dont know what you're talking about, im j wondering if theres a efficient way to parse a sentence and check for bad words, and then mutated bad words aswell. im not that advanced in string manipulation, or regex. \$\endgroup\$
    – Albedo
    Jan 9, 2020 at 18:42
  • 1
    \$\begingroup\$ Sorry, it was a bit hard to understand. What I really mean was: If you let your code analyze my first comment, it won't flag the word poop as a bad word since it is followed by a comma. This is because you are splitting the string at spaces and you further assume that everything between these spaces is a word. \$\endgroup\$ Jan 10, 2020 at 0:45

1 Answer 1


If you care about performance, you should have a look at LPeg. It makes it way easier to handle large numbers of string matching and substitution rules.

For example, you could define patterns and their substitution values like this:

local lpeg = require 'lpeg'

local p = lpeg.P
local bad_word = 
   p"bad" / "good" +
   (p"dumb" + p"stupid") / "$#&*"

local sanitize = lpeg.Cs( (bad_word + p(1))^1 )

print(sanitize:match("this is a bad word"))
print(sanitize:match("python is dumb!"))

Which makes it much easier both to add new entries and to eventually move them into a table or even a separate file.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.