Scripting Helpers is winding down operations and is now read-only. More info→
Ad
Log in to vote
2

What do you do to fix this string manipulation "match" returning nil?

Asked by 7 years ago
Edited 7 years ago

Here's my script:

Players.PlayerAdded:Connect(function(plr)
    plr.Chatted:Connect(function(msg)
        -- Check for admin here.
        if(msg:sub(1,1)=="/")then
            local command, arg1, arg2 = msg:match("^%/(%S+)%s+(%a+)%s(.+)$")

            print(command)
            print(arg1)
            print(arg2)
        end
    end)
end)

Everything's fine, I define the service Players elsewhere but if I added it this would be a standalone script.

The area of problem is here:

local command, arg1, arg2 = msg:match("^(%S+)%s+(%a+)%s(.+)$")

And it works like I want it to. Examples:

"/displayMessage all Hey guys!"

print(command) -- displayMessage
print(arg1) -- all
print(arg2) -- Hey guys!

However some commands will only require two arguments, but then everything's nil.

"/kill me"

print(command)  -- nil
print(arg1)     -- nil
print(arg2)     -- nil

How could I fix this?

This code is mostly from one of my past questions.

I modified Blue's solution a little to fit my new situation here, but I'm still really bad with string manipulation. :c

Thanks for any help!

1 answer

Log in to vote
2
Answered by 7 years ago
Edited 7 years ago

With string.match nil will be returned if there is no capture found / matched.

For an admin script it might be best to build a argument table as this will support a ever changing amount or args ie one function to manage them all.

I find that it can simplify an admin script to just check for the admin command prefix in your case the / then cut out the prefix.

-- we should also check the string size before
if msg:sub(1,1) == '/' then
    msg = msg:sub(2) -- remove the prefix
end

Now that we no longer have the prefix we can split the string using the white space followed by a varying number of characters ie [o or more white space characters] [as many non white space characters as possible]

We can represent this as a string pattern like so %S-(%a+).

But this will not capture any players with any numbers or commands with punctuation in so we need a set resulting in our finished pattern %S-([%a%d%p]+)

Example:-

local testData = {
    '/kill me ??',
    '/ kill me ??',
    '/kill me',
    '/   kill   me',
    '/kill',
    '/ kill ',
    'adsa',
    '/displayMessage all Hey guys!',
    'a',
    '/kill guest11',
    '/kill me!!'
}

for i=1, #testData do
    print('--------- Test ' .. tostring(i) .. ' -----------')
    local msg = testData[i]
    if msg:sub(1,1) == '/' then
        msg = msg:sub(2)
        for c in msg:gmatch('%S-([%a%d%p]+)') do
            print(c, #c)
        end
    end
end

Output:-

--[[
--------- Test 1 -----------
kill 4
me 2
?? 2
--------- Test 2 -----------
kill 4
me 2
?? 2
--------- Test 3 -----------
kill 4
me 2
--------- Test 4 -----------
kill 4
me 2
--------- Test 5 -----------
kill 4
--------- Test 6 -----------
kill 4
--------- Test 7 -----------
--------- Test 8 -----------
displayMessage 14
all 3
Hey 3
guys! 5
--------- Test 9 -----------
--------- Test 10 -----------
kill 4
guest11 7
--------- Test 11 -----------
kill 4
me!! 4
]]

I hope this helps

0
<3 OldPalHappy 1477 — 7y
0
:3 User#5423 17 — 7y
Ad

Answer this question