LUA: Generating Unique Mac from given Number Value - string

I am trying to generate a unique MAC id from given a number value. The length on the number is between 1 to 5 digit. I have formatted the MAC table to place each digit starting from first value of MAC.
local MacFormat ={[1] = "0A:BC:DE:FA:BC:DE",[2] = "00:BC:DE:FA:BC:DE",[3] = "00:0C:DE:FA:BC:DE",[4] = "00:00:DE:FA:BC:DE",[5] = "00:00:0E:FA:BC:DE"}
local idNumbers = {[1] = "1",[2]="12",[3]="123",[4]="1234",[5]="12345"}
for w in string.gfind(idNumbers[3], "(%d)") do
print(w)
str = string.gsub(MacFormat[3],"0",tonumber(w))
end
print(str)
---output 33:3C:DE:FA:BC:DE
--- Desired Output 12:3C:DE:FA:BC:DE
I have tried multiple Patterns with *, +, ., but none is working.

for w in string.gfind(idNumbers[3], "(%d)") do
print(w)
str = string.gsub(MacFormat[3],"0",tonumber(w))
end
print(str)
Your loop body is equivalent to
str = string.gsub("00:0C:DE:FA:BC:DE", "0",1)
str = string.gsub("00:0C:DE:FA:BC:DE", "0", 2)
str = string.gsub("00:0C:DE:FA:BC:DE", "0", 3)
So str is "33:3C:DE:FA:BC:DE"
MacFormat[3] is never altered and the result of gsub is overwritten in each line.

You can build the pattern and replacement dynamically:
local MacFormat ={[1] = "0A:BC:DE:FA:BC:DE",[2] = "00:BC:DE:FA:BC:DE",[3] = "00:0C:DE:FA:BC:DE",[4] = "00:00:DE:FA:BC:DE",[5] = "00:00:0E:FA:BC:DE"}
local idNumbers = {[1] = "1",[2]="12",[3]="123",[4]="1234",[5]="12345"}
local p = "^" .. ("0"):rep(string.len(idNumbers[3])):gsub("(..)", "%1:")
local repl = idNumbers[3]:gsub("(..)", "%1:")
local str = MacFormat[3]:gsub(p, repl)
print(str)
-- => 12:3C:DE:FA:BC:DE
See the online Lua demo.
The pattern is "^" .. ("0"):rep(string.len(idNumbers[3])):gsub("(..)", "%1:"): ^ matches the start of string, then a string of zeros (of the same size a idNumbers, see ("0"):rep(string.len(idNumbers[3]))) follows with a : after each pair of zeros (:gsub("(..)", "%1:")).
The replacement is the idNumbers item with a colon inserted after every second char with idNumbers[3]:gsub("(..)", "%1:").
In this current case, the pattern will be ^00:0 and the replacement will be 12:3.
See the full demo here.

Related

Create a list of strings with one/multiple character replacement

How to create a whole list of string from one string where each string in the list containing exactly one character replacement? The string itself is consisted of only four characters (say: A, B, C, and D), so that the whole list of a string of length n would contain 3n+1 strings with exactly one character replacement.
Example:
inputstr = 'ABCD'
output = ['ABCD', 'BBCD', 'CBCD', 'DBCD', 'AACD', 'ACCD', 'ADCD', 'ABAD', 'ABBD', 'ABDD', 'ABCA', 'ABCB', 'ABCC']
I write the following python code:
strin = 'ABCD'
strout = set()
tempstr1 = ''
tempstr2 = ''
tempstr3 = ''
tempstr4 = ''
for base in range(len(strin)):
if strin[base] == 'A': #this block will be repeated for char B, C and D
tempstr1 = strin.replace(strin[base], 'A')
strout.add(tempstr1)
tempstr1 = ''
tempstr2 = strin.replace(strin[base], 'B')
strout.add(tempstr2)
tempstr2 = ''
tempstr3 = strin.replace(strin[base], 'C')
strout.add(tempseq3)
tempstr3 = ''
tempstr4 = strin.replace(strin[base], 'D')
strout.add(tempseq4)
tempstr4 = ''
return strout
and it works well as long as there is no repeated character (such as 'ABCD'). However, when the input string contains repeated character (such as 'AACD'), it will return less than 3n+1 string. I tried with 'AACD' string and it returns only 10 instead of 13 strings.
Anyone can help?
change
strout = set() ===> strout = list()
I found it. I used a slicing method to create a list of total combination of strings with one replacement.
for i in range(len(seq)):
seqxlist.append(seq[:i] + 'x' + seq[i+1:])
and after that I filter out all the x-replaced strings which are longer than the original string length:
seqxlist = [x for x in seqxlist if (len(x) == len(seq))]
Then, I changed x into any of the substitution characters:
for m in seqxlist:
tempseq1 = m.replace('x', 'A')
outseq.append(tempseq1)
tempseq2 = m.replace('x', 'B')
outseq.append(tempseq2)
tempseq3 = m.replace('x', 'C')
outseq.append(tempseq3)
tempseq4 = m.replace('x', 'D')
outseq.append(tempseq4)
This will create all the possible combinations of string replacement, but still contains duplicates. To remove duplicates, I use set() to the outseq list.

How to convert string to a table?

I have this string text:
text = "hotkey=F4,value=,autoSend=false, hotkey=Shift+F9,value=,autoSend=false, hotkey=F5,value=,autoSend=false"
and I would like to convert it to a table like this one:
local table = {
{hotkey='F4', value=nil, autoSend=false};
{hotkey='Shift+F9', value=nil, autoSend=false};
{hotkey='F5', value=nil, autoSend=false}
}
This solution is limited in scope and will not cover all complexities in the input string. A simple pattern matching could generate tables you are looking for, but use this code to build a better/robust regex for the diversity of your strings
s = "hotkey=F4,value=,autoSend=false, hotkey=Shift+F9,value=,autoSend=false, hotkey=F5,value=,autoSend=false"
local words = {}
for w in s:gmatch("(hotkey=%g-,value=%g-,autoSend=%w*)") do
-- Split string in more managebale parts
-- i-g w = 'hotkey=F4,value=,autoSend=false, hotkey=Shift+F9'
-- Extract indivisual k,v pairs and insert into table as desired
local _hotkey = string.match(w,"hotkey=(%g-),")
local _value = string.match(w,"value=(%g-),")
local _autoSend = string.match(w,"autoSend=(%w+)")
table.insert(words,{hotkey=_hotkey, value=_value, autoSend=_autoSend})
end
for _, w in ipairs(words) do
for k, v in pairs(w) do
print(k .. ':' .. v)
end
end
Regex Explanation
(): Capture string
%g: printable characters except for spaces
%w: alphanumeric characters
* : 0 or more repetitions
- : 0 or more lazy repetitions

Find substring of string w/o knowing the length of string

I have a string x: x = "{abc}{def}{ghi}"
And I need to print the string between second { and second }, in this case def. How can I do this without knowing the length of the string? For example, the string x could also be {abcde}{fghij}{klmno}"
This is where pattern matching is useful:
local x = "{abc}{def}{ghi}"
local result = x:match(".-{.-}.-{(.-)}")
print(result)
.- matches zero or more characters, non-greedy. The whole pattern .-{.-}.-{(.-)} captures what's between the second { and the second }.
Try also x:match(".-}{(.-)}"), which is simpler.
I would go about it in a different manner:
local i, x, result = 1, "{abc}{def}{ghi}"
for w in x:gmatch '{(.-)}' do
if i == 2 then
result = w
break
else
i = i + 1
end
end
print( result )

How to concatenate strings into one using loop?

can someone help me with string concatenate problem. I read data from register. It's function utf(regAddr, length). I get table with decimal numbers, then I transform it into hex and to string in loop. I need concatenate these strings into one.
there is not in Lua something like .= operator
function utf(regAddr, length)
stringTable = {}
table.insert(stringTable, {mb:readregisters(regAddr-1,length)})
for key, value in pairs(stringTable) do
for i=1, length do
v = value[i]
v = lmcore.inttohex(v, 4)
v = cnv.hextostr(v)
log(v)
end
end
end
-- function(regAddr, length)
utf(30,20)
There is no append operator for strings. Strings are immutable values.
The .. operator concatenates two string, producing a third string as a result:
local b = "con"
local c = "catenate"
local a = b .. c -- "concatenate"
The table.concat function concatenates strings in a table, producing a string result:
local t = { "con", "catenate" }
local a = table.concat(t) -- "concatenate"
local t = { "two", "words" }
local a = table.concat(t, " ") -- "two words"
The string.format function takes a format pattern with a list of compatible values, producing a string result:
local b = 2
local c = "words"
local a = string.format("%i %s", b, c) -- "2 words"
local t = { 2, "words" }
local a = string.format("%i %s", unpack(t)) -- "2 words"
If you are accumulating a lot of strings that you eventually want to concatenate, you can use a table as a temporary data structure and concatenate when you are done accumulating:
local t = {}
for i = 1, 1000 do
table.insert(t, tostring(i))
end
local a = table.concat(t) -- "1234...9991000"
For a very large number of strings, you can concatenate incrementally. See LTN 9: Creating Strings Piece by Piece and related discussions.
You should try the table.concat method.
Maybe this other question can help you:
Lua table.concat
Checkout this tutorial http://lua-users.org/wiki/TableLibraryTutorial
this code works:
function utf(regAddr, length)
stringTable = {}
table.insert(stringTable, {mb:readregisters(regAddr-1,length)})
for key, value in pairs(stringTable) do
t = {}
for i=1, length do
v = value[i]
v = lmcore.inttohex(v, 4)
v = cnv.hextostr(v)
table.insert(t, v)
end
a = table.concat(t)
end
end
-- function(regAddr, length)
utf(30,20)

Split string and replace dot char in Lua

I have a string stored in sqlite database and I've assigned it to a var, e.g. string
string = "First line and string. This should be another string in a new line"
I want to split this string into two separated strings, the dot (.) must be replace with (\n) new line char
At the moment I'm stuck and any help would be great!!
for row in db:nrows("SELECT * FROM contents WHERE section='accounts'") do
tabledata[int] = string.gsub(row.contentName, "%.", "\n")
int = int+1
end
I tried the other questions posted here in stachoverflow but with zero luck
What about this solution:`
s = "First line and string. This should be another string in a new line"
a,b=s:match"([^.]*).(.*)"
print(a)
print(b)
Are you looking to actually split the string into two different string objects? If so maybe this can help. It's a function I wrote to add some additional functionality to the standard string library. You can use it as-is or rename it to what ever you like.
--[[
string.split (s, p)
====================================================================
Splits the string [s] into substrings wherever pattern [p] occurs.
Returns: a table of substrings or, if no match is made [nil].
--]]
string.split = function(s, p)
local temp = {}
local index = 0
local last_index = string.len(s)
while true do
local i, e = string.find(s, p, index)
if i and e then
local next_index = e + 1
local word_bound = i - 1
table.insert(temp, string.sub(s, index, word_bound))
index = next_index
else
if index > 0 and index <= last_index then
table.insert(temp, string.sub(s, index, last_index))
elseif index == 0 then
temp = nil
end
break
end
end
return temp
end
Using it is very simple, it returns a tables of strings.
Lua 5.1.4 Copyright (C) 1994-2008 Lua.org, PUC-Rio
> s = "First line and string. This should be another string in a new line"
> t = string.split(s, "%.")
> print(table.concat(t, "\n"))
First line and string
This should be another string in a new line
> print(table.maxn(t))
2

Resources