992 posts
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.
686 posts
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?
992 posts
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.gmatchI 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)
8543 posts
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.
992 posts
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
496 posts
Location
New Zealand
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
992 posts
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
496 posts
Location
New Zealand
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.