Lua string.find() error

So I'm writing a Lua script and I tested it but I got an error that I don't know how to fix:

.\search.lua:10: malformed pattern (missing ']')

Below is my code. If you know what I did wrong, it would be very helpful if you could tell me.

weird = "--[[".."\n"
function readAll(file)
    local c = io.open(file, "rb")
    local j = c:read("*all")
    c:close()
    return(j)
end
function blockActive()
    local fc = readAll("functions.lua")
    if string.find(fc,weird) ~= nil then
        require("blockDeactivated")
        return("false")
    else
        return("true")
    end
end
print(blockActive())

Edit: first comment had the answer. I changed weird = "--[[".."\n" to weird = "%-%-%[%[".."\r" The \n to \r change was because it was actually supposed to be that way in the first place.

Upvotes: 2

Views: 2075

Answers (1)

ATaco
ATaco

Reputation: 486

This errors because string.find uses Lua Patterns.

Most non-alpha-numeric characters, such as "[", ".", "-" etc. convey special meaning.

string.find(fc,weird), or better, fc:find(weird) is trying to parse these special characters, and erroring.

You can use these patterns to cancel out your other patterns, however.

weird = ("--[["):gsub("%W","%%%0") .. "\r?\n"

This is a little daunting, but it will hopefully make sense.

the ("--[[") is the orignal first part of your weird string, working as expected.

:gsub() is a function that replaces a pattern with another one. Once again, see Patterns.

"%W" is a pattern that matches every string that isn't a letter, a number, or an underscore.

%%%0 replaces everything that matches with itself (%0 is a string that represents everything in this match), following a %, which is escaped.

So this means that [[ will be turned into %[%[, which is how find, and similar patterns 'escape' special characters.

The reason \n is now \r?\n refers back to these patterns. This matches it if it ends with a \n, like it did before. However, if this is running on windows, a newline might look like \r\n. (You can read up on this HERE). A ? following a character, \r in this case, means it can optionally match it. So this matches both --[[\n and --[[\r\n, supporting both windows and linux.

Now, when you run your fc:find(weird), it's running fc:find("%-%-%[%[\r?\n"), which should be exactly what you want.

Hope this has helped!

Finished code if you're a bit lazy

weird = ("--[["):gsub("%W","%%%0") .. "\r?\n" // Escape "--[[", add a newline. Used in our find.

// readAll(file)
// Takes a string as input representing a filename, returns the entire contents as a string.
function readAll(file)
    local c = io.open(file, "rb")   // Open the file specified by the argument. Read-only, binary (Doesn't autoformat things like \r\n)
    local j = c:read("*all")        // Dump the contents of the file into a string.
    c:close()                       // Close the file, free up memory.
    return j                        // Return the contents of the string.
end

// blockActive()
// returns whether or not the weird string was matched in 'functions.lua', executes 'blockDeactivated.lua' if it wasn't.
function blockActive()
    local fc = readAll("functions.lua") // Dump the contents of 'functions.lua' into a string.
    if fc:find(weird) then              // If it functions.lua has the block-er.
        require("blockDeactivated")     // Require (Thus, execute, consider loadfile instead) 'blockDeactived.lua'
        return false                    // Return false.
    else
        return true                     // Return true.
    end
end
print(blockActive()) // Test? the blockActve code.

Upvotes: 2

Related Questions