views:

752

answers:

2

I'm trying to use string.find in Lua to parse the contents of a user-entered string. There are up to three different parameters I am trying to find (if the user enters them), but sometimes only one.

The input string in its longer form looks like:

local userInput = "x|y|z"

where x, y, and z can be any character or nothing (empty string, i.e. "") and z can also contain vertical bars/pipes - I only want to divide the string into three sections based on the first two vertical bars ("|") encountered. The difficulty is that the user can also not use that form - he or she can enter simply "x" or "x||z" or "||z", etc. In these case I would still need to get the values of x, y, and z, and it should be clear as to which variables they were assigned to.

For example, I tried this:

local _,_,a,b,c = string.find(usermsg, "([^|]*)|?([^|]*)|?(.+)")

Note first of all that this doesn't even properly fetch a, b, and c properly. But more importantly, when the usermsg was just "x", it set the value of x to variable c, when it should be a. And when the user types "x|y", variable a is x (correct) but variable c is y (wrong, it should be assigned to variable b).

So then I tried doing it separately:

local _,_,a = string.find(usermsg , "([^|]+)|?[^|]*|?.*")
local _,_,b= string.find(usermsg , "[^|]*|([^|]+)|?.*")
local _,_,c= string.find(usermsg , "[^|]*|[^|]*|(.+)")

But this also fails. It matches x, but not y, and c ends up being y plus the pipe and z.

Any help would be appreciated. Thanks! :)

A: 

Give this expression a shot.

"([^|])(?:\|([^|]))?(?:\|(.*))?"

EDIT: Disregard that, forgot that string.find didn't support regular expressions

This should work as you intend

local _,_,a,b = string.find(usermsg, "([^|]*)|?(.*)")
local _,_,b,c = string.find(b, "([^|]*)|?(.*)")
if user input is "a|b|c" that returnsa = "a"b = "a"c = "|b|c"
What version of LUA are you using? I'm testing it on v5.1.4 and it is returning the intended values.
I'm using version 5.1
+1  A: 

Seems that you just look for your typical split function with a max number of splits. Here is mine:

function string.split( str, delim, max, special )
    if max == nil then max = -1 end
    if delim == nil then delim = " " end
    if special == nil then special = False end
    local last, start, stop = 1
    local result = {}
    while max ~= 0 do
        start, stop = str:find(delim, last, not special )
        if start == nil then
            -- if max > #(all ocurances of delim in str), we end here      
            break
        end
        table.insert( result, str:sub( last, start-1 ) )
        last = stop+1
        max = max - 1
    end
    -- add the rest
    table.insert( result, str:sub( last ) )
    return result
end

print( ("A='%s' B='%s' C='%s'"):format(unpack( ("hello|there|world"):split('|', 2) )))
print( ("A='%s' B='%s' C='%s'"):format(unpack( ("||world"):split('|', 2) )))
print( ("A='%s' B='%s' C='%s'"):format(unpack( ("hello||world"):split('|', 2) )))
print( ("A='%s' B='%s' C='%s'"):format(unpack( ("hello|there|"):split('|', 2) )))
print( ("A='%s' B='%s' C='%s'"):format(unpack( ("hello||world|and|the|rest"):split('|', 2) )))

=>

A='hello' B='there' C='world'
A='' B='' C='world'
A='hello' B='' C='world'
A='hello' B='there' C=''
A='hello' B='' C='world|and|the|rest'
THC4k