How would I convert a string into a table? - lua

I have been trying to convert a string into a table for example:
local stringtable = "{{"user123","Banned for cheating"},{"user124","Banned for making alt accounts"}}"
Code:
local table = "{{"user123","Banned for cheating"},{"user124","Banned for making alt accounts"}}"
print(table[1])
Output result:
Line 3: nil
Is there any sort of method of converting a string into a table? If so, let me know.

First of all, your Lua code will not work. You cannot have unescaped double quotes in a string delimited by double quotes. Use single quotes(') within a "-string, " within '...' or use heredoc syntax to be able to use both types of quotes, as shall I in the example below.
Secondly, your task cannot be solved with a regular expression, unless your table structure is very rigid; and even then Lua patterns will not be enough: you will need to use Perl-compatible regular expressions from Lua lrexlib library.
Thirdly, fortunately, Lua has a Lua interpreter available at runtime: the function loadstring. It returns a function that executes Lua code in its argument string. You just need to prepend return to your table code and call the returned function.
The code:
local stringtable = [===[
{{"user123","Banned for cheating"},{"user124","Banned for making alt accounts"}}
]===]
local tbl_func = loadstring ('return ' .. stringtable)
-- If stringtable is not valid Lua code, tbl_func will be nil:
local tbl = tbl_func and tbl_func() or nil
-- Test:
if tbl then
for _, user in ipairs (tbl) do
print (user[1] .. ': ' .. user[2])
end
else
print 'Could not compile stringtable'
end

Related

calculating string length causes confustion

I am confused by the following output:
local a = "string"
print(a.len) -- function: 0xc8a8f0
print(a.len(a)) -- 6
print(len(a))
--[[
/home/pi/test/wxlua/wxLua/ZeroBraneStudio/bin/linux/armhf/lua: /home/pi/Desktop/untitled.lua:4: attempt to call global 'len' (a nil value)
stack traceback:
/home/pi/Desktop/untitled.lua:4: in main chunk
[C]: ?
]]
What is the proper way to calculate a string length in Lua?
Thank you in advance,
You can use:
a = "string"
string.len(a)
Or:
a = "string"
a:len()
Or:
a = "string"
#a
EDIT: your original code is not idiomatic but is also working
> a = "string"
> a.len
function: 0000000065ba16e0
> a.len(a)
6
The string a is linked to a table (named metatable) containing all the methods, including len.
A method is just a function, taking the string as the first parameter.
function a.len (string) .... end
You can call this function, a.len("test") just like a normal function. Lua has a special syntax to make it easier to write. You can use this special syntax and write a:len(), it will be equivalent to a.len(a).
print(a.len) -- function: 0xc8a8f0
This prints a string representation of a.len which is a function value. All strings share a common metatable.
From Lua 5.4 Reference Manual: 6.4 String Manipulation:
The string library provides all its functions inside the table string.
It also sets a metatable for strings where the __index field points to
the string table. Therefore, you can use the string functions in
object-oriented style. For instance, string.byte(s,i) can be written
as s:byte(i).
So given that a is a string value, a.len actually refers to string.len
For the same reason
print(a.len(a))
is equivalent to print(string.len(a)) or print(a:len()). This time you called the function with argument a instead of printing its string representation so you print its return value which is the length of string a.
print(len(a))
on the other hand causes an error because you attempt to call a global nil value. len does not exist in your script. It has never been defined and is hence nil. Calling nil values doesn't make sense so Lua raises an error.
According to Lua 5.4 Reference Manual: 3.4.7 Length Operator
The length of a string is its number of bytes. (That is the usual
meaning of string length when each character is one byte.)
You can also call print(#a) to print a's length.
The length operator was introduced in Lua 5.1,

How to remove white spaces after "(" in string?

A lua newbie here.
I would like to replace the string '$\\psi\\left( y\\right)$' with '$\\psi\\left(y\\right)$' i.e. remove any white spaces that show up after ( and before the next non-white space character.
I have been trying gsub but each attempt did not work. This is what I tried
function foo(s)
print('before s = '..s)
str=string.gsub(s,"\\left( ","\\left(")
print('after s= '..str)
return str
end
And tried
function foo(s)
print('before s = '..s)
str=string.gsub(s,"\\left(%s+","\\left(")
print('after s= '..str)
return str
end
And few other variations. But each time I call the function as follows
foo('$\\psi\\left( y\\right)$')
The string returned is the same. The white space is still there.
What is the correct way to do this? Using Lua 5.2.4 on linux.
I intend to use this function inside lualatex, and these strings will be passed from latex to lua as strings. But I am now trying this function in standalone lua installation on Linux first to see if it works before I use it inside Lualatex.
Magic characters like ( need to be escaped.
Please refer to https://www.lua.org/manual/5.3/manual.html#6.4.1
Replace "\\left(%s+" with "\\left%(%s+" or "\\left( +" with "\\left%( +"
Looks to me like some bug. This should actually result in an "unfinished capture" error. At least it would if ( was the first character in the pattern.

send hex variable via TCP socket

Probably it's an easy thing, but I'm a Lua beginner...
I'm creating a very simple QSC QSYS plugin to control a projection server using KVL API. Server API is based on hex strings.
For example this command asks the server to load a the playlist with 9bf5455689ed4c019731c6dd3c071f0e uuid:
Controls["LoadSPL"].EventHandler = function()
sock:Write(
"\x06\x0e\x2b\x34\x02\x05\x01\x0a\x0e\x10\x01\x01\x01\x03\x09\x00\x83\x00\x00\x14\x00\x00\x00\x01\x9b\xf5\x45\x56\x89\xed\x4c\x01\x97\x31\xc6\xdd\x3c\x07\x1f\x0e"
)
end
Now I need to be able to create a string with a variable UUID, according to the text indicated in a textbox (or a list of available UUIDs read from the server) in the user interface.
I will concatenate this string to the fixed part of the command.
How can I correctly make a string like
ad17fc696b49454db17d593db3e553e5 become
\xad\x17\xfc\x69\x6b\x49\x45\x4d\xb1\x7d\x59\x3d\xb3\xe5\x53\xe5?
Try this:
local input = "ad17fc696b49454db17d593db3e553e5"
local output = input:gsub("%w%w", function(s) return string.char(tonumber(s, 16)) end)
Explanation: this takes every pair of characters, interprets them as base 16 numeric string, and then takes the character with that number, and uses that to replace the original characters.
EDIT: To make it clear what's going on, and why the other answers are wrong, backslash escape sequences like \xad are a feature of the Lua source code, in memory it's represented by a byte with value 173, just like A is represented by a byte with value 65. Trying to concatenate a literal backslash character with hexadecimal characters does not create an escape code. So the way to do that is manually with string.char.
#! /usr/bin/env lua
str = 'ad17fc696b49454db17d593db3e553e5'
strx = ''
for i = 1, #str, 2 do -- loop through every-other position in your string
chars = str :sub( i, i+1 ) -- capture every 2 chars
strx = strx ..'\\x' ..chars
end -- append a literal backslash, the letter x, then those 2 chars
target = [[\xad\x17\xfc\x69\x6b\x49\x45\x4d\xb1\x7d\x59\x3d\xb3\xe5\x53\xe5]]
print( x, x == target ) -- print results, and test if it meets expected target
\xad\x17\xfc\x69\x6b\x49\x45\x4d\xb1\x7d\x59\x3d\xb3\xe5\x53\xe5 true
This can be code-golfed into a one-liner
x=''for i=1,#s,2 do x=x..'\\x'..s:sub(i,i+1)end

Torch: CmdLine() : passing array of elements to a variable from command line

I am using torch.CmdLine() to parse command line arguments in Torch. I need to pass an array of elements for one of the variables. I am not aware of any mechanisms for passing an array of elements for a variable. So I am treating that variable as a string and passing the array of elements separated by space and enclosed within double quotes from the command line.
The code for doing this looks as follows:
cmd = torch.CmdLine()
cmd:text('Training')
cmd:text()
cmd:option('-cuda_device',"1 2 3")
params = cmd:parse(arg or {})
--parse the string to extract array of numbers
for i=1,string.len(params.cuda_device) do
if params.cuda_device[i] ~= ' ' then
-- some code here
end
end
Here since Lua string indexing is not provided by default, I had to override __index to enable indexing of string as follows,
getmetatable('').__index = function(str,i) return string.sub(str,i,i) end
This works for parsing the string to an array of numbers.
However, overriding __index breaks the code somewhere else, throwing the following error:
qlua: /home/torch/install/share/lua/5.1/torch/init.lua:173: bad argument #2 to '__index' (number expected, got string)
I can do some workarounds to fix this (instead of overriding __index use string.sub(str,i,i) directly) but I would like to know your suggestions in passing an array of elements using torch.CmdLine() in an elegant way--if applicable.
Thanks in Advance.
You can pass the list as a sequence of words separated by spaces as you have done, and after cmd:parse you can explode the string into an array using:
params = cmd:parse()
local tmptab = {}
for word in params.cuda_device:gmatch("%w+") do
tmptab[#tmptab +1] = word
end
params.cuda_device = tmptab
for i,v in pairs(params.cuda_device) do
-- some code here
end
That will explode the string parsed by cmd:parse() into an table with each word on it's on index, and there would be no need to delve into string metamethods...
Also, you can avoid the error doing this:
getmetatable('').__index = function(str,i)
if(type(i) == "number") then
return string.sub(str,i,i)
else
return ""
end
end
It is odd that you have tried to index a string using another string, however...

string.format variable number of arguments

Luas string.format is pretty straight forward, if you know what to format.
However, I stuck at writing a function which takes a wildcard-string to format, and a variable number of arguments to put into that blank string.
Example:
str = " %5s %3s %6s %6s",
val = {"ttyS1", "232", "9600", "230400"}
Formatting that by hand is pretty easy:
string.format( str, val[1], val[2], val[3], val[4] )
Which is the same as:
string.format(" %5s %3s %6s %6s", "ttyS1, "232", "9600","230400")
But what if I wan't to have a fifth or sixth argument?
For example:
string.format(" %1s %2s %3s %4s %5s %6s %7s %", ... )
How can I implement a string.format with an variable number of arguments?
I want to avoid appending the values one by one because of performance issues.
The application runs on embedded MCUs.
Generate arbitrary number of repeats of whatever format you want with string.rep if format is the same for all arguments. Or fill table with all formats and use table.concat. Remember that you don't need to specify index of argument in format if you don't want to reorder them.
If you just need to concatenate strings together separated by space, use more suitable tool: table.concat(table_of_strings, ' ').
You can create a table using varargs:
function foo(fmt, ...)
local t = {...}
return t[6] -- might be nil
end
Ps, don't use # on the table if you expect the argument list might contain nil. Instead use select("#", ...).

Resources