This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
BigSHinyToys's profile picture

[SOLVED] string seperation with quote's like in MS-DOS / CMD

Started by BigSHinyToys, 12 August 2012 - 12:35 PM
BigSHinyToys #1
Posted 12 August 2012 - 02:35 PM
I am attempting to make a MS-DOS 3.30 for Computer craft. To be able to do this using original command syntax I have to break a string input by user into separate variables. For those unfamiliar with MS-DOS it is predecessor to CMD in windows.

I will list some examples bellow

local tTable = {}
tTable[1] = [[dir "C:\random files"]]
tTable[2] = [[dir "C:\random files" /b]]
tTable[3] = [[help dir]]
tTable[4] = [[dir /?]]
tTable[5] = [[del /p "C:\hello.txt" "D:\random file name.exe" "E:\other Random file.exe"]]
for i = 1,#tTable do -- use ipair if you prefer
print(tTable[i])
end
I need a function / pattern for string.gmatch (s, pattern) that can break these into individual pieces.Using the current section of code from shell causes the "" to be ignored and the spaces in the middle to be where the list is cut. I need everything spaces and all between the "" to be read in as one variable and the others to be split as normal by space.

I have had no luck finding a solution to this problem I hope with your help to proceed with the project Thanks for any help in advance.
D3matt #2
Posted 12 August 2012 - 03:41 PM
I'm not sure about string.match, but have you tried searching for the " and then using string.sub to get what's between them?
BigSHinyToys #3
Posted 12 August 2012 - 04:05 PM
I'm not sure about string.match, but have you tried searching for the " and then using string.sub to get what's between them?
to Quote shell form CC lines 171 to 186 (the section that breaks user input into sections before execution)

while not bExit do
    write( shell.dir() .. "> " )
    local sLine = read( nil, tCommandHistory )
    table.insert( tCommandHistory, sLine )
   
    local tWords = {}
    for match in string.gmatch(sLine, "[^ t]+") do
	    table.insert( tWords, match )
    end
    local sCommand = tWords[1]
    if sCommand then
	    shell.run( sCommand, unpack( tWords, 2 ) )
    end
end
http://www.lua.org/manual/5.1/manual.html#pdf-string.gmatch
I don't mean string.match() I meant string.gmatch() the above shows how shell handles this task I am looking for something like this but with Quoted line support.

If worst comes to worst I will be using a string.sub after locating "" symbles But That is not a very clean implementation. if string.gmatch() is capable and i think it is then It would be a better option as stated I would like a function or pattern.Alas I have had no experience with patterns (with contest of lua string functions)
Lyqyd #4
Posted 12 August 2012 - 05:41 PM
You should probably use a two-pass system to catch the quotes (use the balanced marker matching first), and then separate by spaces in the second pass.
BigSHinyToys #5
Posted 12 August 2012 - 07:36 PM
You should probably use a two-pass system to catch the quotes (use the balanced marker matching first), and then separate by spaces in the second pass.
That sounds like a good idea Thanks
Xtansia #6
Posted 13 August 2012 - 05:21 AM
I know you may have solved this but I just wanted to post my solution:


local function split(subj)
    local pos = 1
    local function parsebypattern(pat)
        local capture, newpos = string.match(subj, pat, pos)
        if newpos then pos = newpos; return capture end
    end
    local function parsespaces() return parsebypattern("^([ tn]*)()") end
    local function parseword() return parsebypattern("^([^ tn]+)()") end
    local function parsequotes() return parsebypattern("^"(.-)"()") end
    local t = {}
    while true do
        parsespaces()
        local r = parsequotes() or parseword()
        if r then table.insert(t, r) else break end
    end
    return t
end

local s = [["hello there" how are you]]
for k,v in pairs(split(s)) do print(v) end
BigSHinyToys #7
Posted 13 August 2012 - 05:34 AM
I know you may have solved this but I just wanted to post my solution:
– code –
I had already built a splitter But is was a messy badly written piece of (code or "cr@p"). Thank you I will use your code (with permissions / crediting) if you allow.

I set it up to test with the provided list works like a charm
Spoiler

local tTable = {}
tTable[1] = [[dir "C:random files"]]
tTable[2] = [[dir "C:random files" /b]]
tTable[3] = [[help dir]]
tTable[4] = [[dir /?]]
tTable[5] = [[del /p "C:hello.txt" "D:random file name.exe" "E:other Random file.exe"]]
local function split(subj)
    local pos = 1
    local function parsebypattern(pat)
	    local capture, newpos = string.match(subj, pat, pos)
	    if newpos then pos = newpos; return capture end
    end
    local function parsespaces() return parsebypattern("^([ tn]*)()") end
    local function parseword() return parsebypattern("^([^ tn]+)()") end
    local function parsequotes() return parsebypattern("^"(.-)"()") end
    local t = {}
    while true do
	    parsespaces()
	    local r = parsequotes() or parseword()
	    if r then table.insert(t, r) else break end
    end
    return t
end
for i = 1,#tTable do -- use ipair if you prefer
print("TEST > "..tTable[i])
local s = tTable[i]
for k,v in pairs(split(s)) do
  print(v)
end
sleep(1)
end
Xtansia #8
Posted 13 August 2012 - 06:30 AM
I know you may have solved this but I just wanted to post my solution:
– code –
I had already built a splitter But is was a messy badly written piece of (code or "cr@p"). Thank you I will use your code (with permissions / crediting) if you allow.

I set it up to test with the provided list works like a charm

Yeah I don't mind, wouldn't have posted it for you if I didn't want people using it.