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 )
Related
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.
string = 'jackk982'
y = 0
def is_alpha(x):
global y
for char in x:
for num in range(97, 123):
if ord(char) == num:
y += 1
x = x[y:]
return x
print(is_alpha(string))
I cant seem to find anything wrong, but the output does not give me 982. How can I fix this?
Okay, I don't know what you were trying to do with the two for-loops but the simplest way would be the following:
string = 'jackk982'
def get_string(x):
for a in range(0, len(x)):
if x[a].isdigit():
return x[a:]
print(get_string(string))
For the string jackk982, it returns 982. For another input hahahahlol5hf it returns 5hf.
The code first checks if one of the characters in the string is a number and if so it returns the rest of the string from that character including the number.
Lets say with a string = "AABBAAAAABBBBAAABBBBAA"
I want to return string split by the odd lengths of the string (i.e when A = 5 or A = 3),
What I want returned is 1) AABBAAAAA 2)BBBBAAA 3)BBBBAA,
How can I do that?
I tried using regex [A]+[B]+ for a slightly different case
One option might be to regex iterate using re.finditer with the following pattern:
.*?(?:AAA(?:AA)?|$)
This pattern will non greedily consume until reaching either 3 A's, 5 A's, or the end of the string. Then, we can print out each complete match as we iterate.
input = 'AABBAAAAABBBBAAABBBBAA'
pattern = '.*?(?:AAA(?:AA)?|$)'
for match in re.finditer(pattern, input):
print match.group()
This prints:
AABBAAAAA
BBBBAAA
BBBBAA
You can use itertools.groupby:
s = 'BBAAAAABBBBAAABBBBAA'
from itertools import groupby
out = ['']
for v, g in groupby(s):
l = [*g]
out[-1] += ''.join(l)
if v == 'A' and len(l) in (3, 5):
out.append('')
print(out)
Prints:
['BBAAAAA', 'BBBBAAA', 'BBBBAA']
I'm trying to do a library in Lua with some function that manipulate strings.
I want to do a function that changes the letter case to upper only on odd characters of the word.
This is an example:
Input: This LIBRARY should work with any string!
Result: ThIs LiBrArY ShOuLd WoRk WiTh AnY StRiNg!
I tried with the "gsub" function but i found it really difficult to use.
This almost works:
original = "This LIBRARY should work with any string!"
print(original:gsub("(.)(.)",function (x,y) return x:upper()..y end))
It fails when the string has odd length and the last char is a letter, as in
original = "This LIBRARY should work with any strings"
I'll leave that case as an exercise.
First, split the string into an array of words:
local original = "This LIBRARY should work with any string!"
local words = {}
for v in original:gmatch("%w+") do
words[#words + 1] = v
end
Then, make a function to turn words like expected, odd characters to upper, even characters to lower:
function changeCase(str)
local u = ""
for i = 1, #str do
if i % 2 == 1 then
u = u .. string.upper(str:sub(i, i))
else
u = u .. string.lower(str:sub(i, i))
end
end
return u
end
Using the function to modify every words:
for i,v in ipairs(words) do
words[i] = changeCase(v)
end
Finally, using table.concat to concatenate to one string:
local result = table.concat(words, " ")
print(result)
-- Output: ThIs LiBrArY ShOuLd WoRk WiTh AnY StRiNg
Since I am coding mostly in Haskell lately, functional-ish solution comes to mind:
local function head(str) return str[1] end
local function tail(str) return substr(str, 2) end
local function helper(str, c)
if #str == 0 then
return ""
end
if c % 2 == 1 then
return toupper(head(str)) .. helper(tail(str),c+1)
else
return head(str) .. helper(tail(str), c+1)
end
end
function foo(str)
return helper(str, 1)
end
Disclaimer: Not tested, just showing the idea.
And now for real, you can treat a string like a list of characters with random-access with reference semantics on []. Simple for loop with index should do the trick just fine.
Problem Description:
HI there. I'm trying to figure out how to use the lua function "string.gsub". I've been reading the manual which says:
This is a very powerful function and can be used in multiple ways.
Used simply it can replace all instances of the pattern provided with
the replacement. A pair of values is returned, the modified string and
the number of substitutions made. The optional fourth argument n can
be used to limit the number of substitutions made:
> = string.gsub("Hello banana", "banana", "Lua user")
Hello Lua user 1
> = string.gsub("banana", "a", "A", 2) -- limit substitutions made to 2
bAnAna 2
Question
When it says that a pair of values is returned; how do I get the new string value?
Code
local email_filename = "/var/log/test.txt"
local email_contents_file_exists = function(filename)
file = io.open(filename, "r")
if file == nil then
return false
else
file.close(file)
return true
end
end
local read_email_contents_file = function()
print('inside the function')
if not email_contents_file_exists(email_filename) then
return false
end
local f = io.open(email_filename, "rb")
local content = f:read("*all")
f:close()
print(content)
--content = string.gsub(content, '[username]', 'myusername')
--local tmp {}
--tmp = string.gsub(content, '[username]', 'myusername')
print(string.gsub(content, '[username]', 'myusername'))
return content
end
local test = read_email_contents_file()
What I've Tried So Far:
I've tried just printing the results, as you see above. That returns a bunch of garbled text. Tried saving to original string and I've also tried saving the results to an array (local tmp = {})
Any suggestions?
> = string.gsub('banana', 'a', 'A', 2)
bAnAna 2
> = (string.gsub('banana', 'a', 'A', 2))
bAnAna
You were going pretty good with reading the Lua users wiki.
In Lua, when you a function returns more than one value, you can access them all as follows
function sth()
return 1, "hi", false
end
x, y, z, a, b, c = sth() -- x = 1; y = "hi" and z = false(boolean); a = b = c = nil
Now, coming back to string.gsub function. It returns two values. The first being the processed string and the second being the number of time gsub performed itself on the input string.
So, to get the new string value, something like this would be best:
local tempString = string.gsub(content, '[username]', 'myusername')
OR
local tempString = content:gsub( '[username]', 'myusername' )
Ofcourse, here, you need to be aware about the various patterns used in Lua which are mentioned in the Programming in Lua book.
You need to escape [ and ] because they are magic characters in Lua patterns.