How to convert string to a table? - string

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

Related

LUA: Generating Unique Mac from given Number Value

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.

How to separate a string by Capital Letter?

I currently have to a code in ABAP which contains a String that has multiple words that start with Capital letters/Uppercase and there is no space in-between.
I have to separate it into an internal table like this:
INPUT :
NameAgeAddress
OUTPUT :
Name
Age
Address
Here is the shortest code I could find, which uses a regular expression combined with SPLIT:
SPLIT replace( val = 'NameAgeAddress' regex = `(?!^.)\u` with = ` $0` occ = 0 )
AT ` `
INTO TABLE itab.
So, replace converts 'NameAgeAddress' into 'Name Age Address' and SPLIT puts the 3 words into an internal table.
Details:
(?!^.) to say the next character to find (\u) should not be the first character
\u being any upper case letter
$0 to replace the found string ($0) by itself preceded with a space character
occ = 0 to replace all occurrences
Unfortunately, the SPLIT statement in ABAP does not allow a regex as separator expression. Therefore, we have to use progressive matching, which is a bit awkward in ABAP:
report zz_test_split_capital.
parameters: p_input type string default 'NameAgeAddress' lower case.
data: output type stringtab,
off type i,
moff type i,
mlen type i.
while off < strlen( p_input ).
find regex '[A-Z][^A-Z]*'
in section offset off of p_input
match offset moff match length mlen.
if sy-subrc eq 0.
append substring( val = p_input off = moff len = mlen ) to output.
off = moff + mlen.
else.
exit.
endif.
endwhile.
cl_demo_output=>display_data( output ).
Just for comparison, the following statement would do the job in Perl:
my $input = "NameAgeAddress";
my #output = split /(?=[A-Z])/, $input;
# gives #output = ('Name','Age','Address')
It is easy with using regular expressions. The solution could look like this.
REPORT ZZZ.
DATA: g_string TYPE string VALUE `NameAgeAddress`.
DATA(gcl_regex) = NEW cl_abap_regex( pattern = `[A-Z]{1}[a-z]+` ).
DATA(gcl_matcher) = gcl_regex->create_matcher( text = g_string ).
WHILE gcl_matcher->find_next( ).
DATA(g_match_result) = gcl_matcher->get_match( ).
WRITE / g_string+g_match_result-offset(g_match_result-length).
ENDWHILE.
For when regular expressions are just overkill and plain old ABAP will do:
DATA(str) = 'NameAgeAddress'.
IF str CA sy-abcde.
DATA(off) = 0.
DO.
data(tailstart) = off + 1.
IF str+tailstart CA sy-abcde.
DATA(len) = sy-fdpos + 1.
WRITE: / str+off(len).
add len to off.
ELSE.
EXIT.
ENDIF.
ENDDO.
write / str+off.
ENDIF.
If you do not want to use or cannot use Regex, here another solution:
DATA: lf_input TYPE string VALUE 'NameAgeAddress',
lf_offset TYPE i,
lf_current_letter TYPE char1,
lf_letter_in_capital TYPE char1,
lf_word TYPE string,
lt_word LIKE TABLE OF lf_word.
DO strlen( lf_input ) TIMES.
lf_offset = sy-index - 1.
lf_current_letter = lf_input+lf_offset(1).
lf_letter_in_capital = to_upper( lf_current_letter ).
IF lf_current_letter = lf_letter_in_capital.
APPEND INITIAL LINE TO lt_word ASSIGNING FIELD-SYMBOL(<ls_word>).
ENDIF.
IF <ls_word> IS ASSIGNED. "if input string does not start with capital letter
<ls_word> = <ls_word> && lf_current_letter.
ENDIF.
ENDDO.

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)

string matching in matlab

I have two short (S with the size of 1x10) and very long (L with the size of 1x1000) strings and I am going to find the locations in L which are matched with S.
In this specific matching, I am just interested to match some specific strings in S (the black strings). Is there any function or method in matlab that can match some specific strings (for example string numbers of 1, 5, 9 in S)?
If I understand your question correctly, you want to find substrings in L that contain the same letters (characters) as S in certain positions (let's say given by array idx). Regular expressions are ideal here, so I suggest using regexp.
In regular expressions, a dot (.) matches any character, and curly braces ({}) optionally specify the number of desired occurrences. For example, to match a string of length 6, where the second character is 'a' and the fifth is 'b', our regular expression could be any of the following syntaxes:
.a..b.
.a.{2}b.
.{1}a.{2}b.{1}
any of these is correct. So let's construct a regular expression pattern first:
in = num2cell(diff([0; idx(:); numel(S) + 1]) - 1); %// Intervals
ch = num2cell(S(idx(:))); %// Matched characters
C = [in(:)'; ch(:)', {''}];
pat = sprintf('.{%d}%c', C{:}); %// Pattern for regexp
Now all is left is to feed regexp with L and the desired pattern:
loc = regexp(L, pat)
and voila!
Example
Let's assume that:
S = 'wbzder'
L = 'gabcdexybhdef'
idx = [2 4 5]
First we build a pattern:
in = num2cell(diff([0; idx(:); numel(S) + 1]) - 1);
ch = num2cell(S(idx(:)));
C = [in(:)'; ch(:)', {''}];
pat = sprintf('.{%d}%c', C{:});
The pattern we get is:
pat =
.{1}b.{1}d.{0}e.{1}
Obviously we can add code that beautifies this pattern into .b.de., but this is really an unnecessary optimization (regexp can handle the former just as well).
After we do:
loc = regexp(L, pat)
we get the following result:
loc =
2 8
Seems correct.

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