How to remove all characters before last matching character in Lua - lua

So i'm a little bit confused about Lua pattern matching. I have a script to log history of videos played with MPV, but i don't need full path there, just filename is enough, so i wanted to remove all everything before last / char. In Python i would do simple
filename = re.sub(r'.*/', '', path)
But i failed horribly using Lua pattern matching. How does one do that?
Example input with desirable output:
>>> path = "/some/path/to/file.mkv"
>>> filename = re.sub(r'.*/', '', path)
>>> filename
'file.mkv'

Seems i have figured it out by myself, oh well. Used this kind of pattern:
path = "/path/to/some/file"
filename = path:gsub(".*/", "")
filename now contains only "file".
EDIT: As suggested, i changed path:gsub("(.*).*/",'') to path:gsub(".*/", "") instead since it's much more readable syntax .

Related

sed: search for a pattern after a particular line containing a keyword

input file:
new file
myString
abc
myString
xyz
pattern
file txt
myString
almost the end of file
myString
end of file
The input file contains multiple occurrences of myString throughout the entire file but I need to replace only the first occurrence of myString that occurs after another pattern pattern.
Also, there are no specific number of lines between pattern and first occurrence of myString.
desired output:
new file
myString
abc
myString
xyz
pattern
file txt
replacement_pattern
almost the end of file
myString
end of file
I want to do this task using sed, if possible
This might work for you (GNU sed):
sed '/pattern/{:a;N;s/myString/myReplacement/;Ta}' file
Gather up lines after finding one that contains pattern and replace the first match with a replacement string.
Alternative:
sed '/pattern/{:a;n;/myString/!ba;s//myReplacement/}' file
Same idea but using traditional sed commands rather that GNU specific.
N.B. This solution uses n instead of N which may affect the speed of the result (as it uses the implicit print for each line that is not matched by myString) in contrast to using less memory and printing all lines once a match is found.
The simple would be just:
/pattern/,/myString/s/myString/replacement_pattern/
For the first and only first myString in file I think there should be something simple, but I ended up with:
/pattern/,${ x; /myString/!{ x; //{ h; s//replacement_pattern/}; x}; x}'
A bit shorter:
/pattern/,${ /myString/{ x; //!{ g; s//replacement_pattern/; x}; x} }

extract data from string in lua - SubStrings and Numbers

I'm trying to phrase a string for a hobby project and I'm self taught from code snips from this site and having a hard time working out this problem. I hope you guys can help.
I have a large string, containing many lines, and each line has a certain format.
I can get each line in the string using this code...
for line in string.gmatch(deckData,'[^\r\n]+') do
print(line) end
Each line looks something like this...
3x Rivendell Minstrel (The Hunt for Gollum)
What I am trying to do is make a table that looks something like this for the above line.
table = {}
table['The Hunt for Gollum'].card = 'Rivendell Minstrel'
table['The Hunt for Gollum'].count = 3
So my thinking was to extract everything inside the parentheses, then extract the numeric vale. Then delete the first 4 chars in the line, as it will always be '1x ', '2x ' or '3x '
I have tried a bunch of things.. like this...
word=str:match("%((%a+)%)")
but it errors if there are spaces...
my test code looks like this at the moment...
line = '3x Rivendell Minstrel (The Hunt for Gollum)'
num = line:gsub('%D+', '')
print(num) -- Prints "3"
card2Fetch = string.sub(line, 5)
print(card2Fetch) -- Prints "Rivendell Minstrel (The Hunt for Gollum)"
key = string.gsub(card2Fetch, "%s+", "") -- Remove all Spaces
key=key:match("%((%a+)%)") -- Fetch between ()s
print(key) -- Prints "TheHuntforGollum"
Any ideas how to get the "The Hunt for Gollum" text out of there including the spaces?
Try a single pattern capturing all fields:
x,y,z=line:match("(%d+)x%s+(.-)%s+%((.*)%)")
t = {}
t[z] = {}
t[z].card = y
t[z].count = x
The pattern reads: capture a run of digits before x, skip whitespace, capture everything until whitespace followed by open parenthesis, and finally capture everything until a close parenthesis.

Lua string.find() error

So I'm writing a Lua script and I tested it but I got an error that I don't know how to fix:
.\search.lua:10: malformed pattern (missing ']')
Below is my code. If you know what I did wrong, it would be very helpful if you could tell me.
weird = "--[[".."\n"
function readAll(file)
local c = io.open(file, "rb")
local j = c:read("*all")
c:close()
return(j)
end
function blockActive()
local fc = readAll("functions.lua")
if string.find(fc,weird) ~= nil then
require("blockDeactivated")
return("false")
else
return("true")
end
end
print(blockActive())
Edit: first comment had the answer. I changed
weird = "--[[".."\n" to weird = "%-%-%[%[".."\r" The \n to \r change was because it was actually supposed to be that way in the first place.
This errors because string.find uses Lua Patterns.
Most non-alpha-numeric characters, such as "[", ".", "-" etc. convey special meaning.
string.find(fc,weird), or better, fc:find(weird) is trying to parse these special characters, and erroring.
You can use these patterns to cancel out your other patterns, however.
weird = ("--[["):gsub("%W","%%%0") .. "\r?\n"
This is a little daunting, but it will hopefully make sense.
the ("--[[") is the orignal first part of your weird string, working as expected.
:gsub() is a function that replaces a pattern with another one. Once again, see Patterns.
"%W" is a pattern that matches every string that isn't a letter, a number, or an underscore.
%%%0 replaces everything that matches with itself (%0 is a string that represents everything in this match), following a %, which is escaped.
So this means that [[ will be turned into %[%[, which is how find, and similar patterns 'escape' special characters.
The reason \n is now \r?\n refers back to these patterns. This matches it if it ends with a \n, like it did before. However, if this is running on windows, a newline might look like \r\n. (You can read up on this HERE). A ? following a character, \r in this case, means it can optionally match it. So this matches both --[[\n and --[[\r\n, supporting both windows and linux.
Now, when you run your fc:find(weird), it's running fc:find("%-%-%[%[\r?\n"), which should be exactly what you want.
Hope this has helped!
Finished code if you're a bit lazy
weird = ("--[["):gsub("%W","%%%0") .. "\r?\n" // Escape "--[[", add a newline. Used in our find.
// readAll(file)
// Takes a string as input representing a filename, returns the entire contents as a string.
function readAll(file)
local c = io.open(file, "rb") // Open the file specified by the argument. Read-only, binary (Doesn't autoformat things like \r\n)
local j = c:read("*all") // Dump the contents of the file into a string.
c:close() // Close the file, free up memory.
return j // Return the contents of the string.
end
// blockActive()
// returns whether or not the weird string was matched in 'functions.lua', executes 'blockDeactivated.lua' if it wasn't.
function blockActive()
local fc = readAll("functions.lua") // Dump the contents of 'functions.lua' into a string.
if fc:find(weird) then // If it functions.lua has the block-er.
require("blockDeactivated") // Require (Thus, execute, consider loadfile instead) 'blockDeactived.lua'
return false // Return false.
else
return true // Return true.
end
end
print(blockActive()) // Test? the blockActve code.

Don't match dot in beginning of string

I have one path in form of string like this Folder1/File.png
But in this string sometimes if file is hidden or folder is hidden I don't want it to be matched by my regex.
regex = %r{([a-zA-Z0-9_ -]*)\/[^.]+$}
input_path = "Folder_1/.file" # This shouldn't be matched.
input_path = "Folder/file.png" # This should be matched.
But my regex works for first input but its not even matching second one.
You are currently looking for \/[^.]+$, that is a / followed by any character except . until the end. Since the filename+extension format has a . character, it fails to match the second case.
Instead of using [^.]+$, check only that the character following / is not ., and match everything after that:
([a-zA-Z0-9_ -]*)\/[^.].*$
While there are some suggestions here that work, my suggestion would be
\/[^.][^\/\n]+$
It finds a slash, followed by anything but a dot, which in turn is followed by one, or more, of anything but a slash or a newline.
To handle the two lines given as an example,
Folder_1/.file
Folder/file.png
it takes 8 steps.
The suggested ones all work, but ([a-zA-Z0-9_ -]*)\/[^.] takes 75 steps, ([a-zA-Z0-9_ -]*)\/[^.]+\.[^.]+\z 78 steps and ([a-zA-Z0-9_ -]*)\/[^.].*$ takes 77 steps.
This may be totally irrelevant and I may have missed some angle, but I wanted to mention it ;)
Se it here at regex101.
regex = %r{([a-zA-Z0-9_ -]*)\/[^.]}

Lua cmd-line string

Say I call Lua with this cmd:
luajit neuralnetwork.lua --satEpoch "somestring" --maxEpoch 50
How can I access this same cmd-line string from Lua?
I know about the arg table, but it removes all quotes from the original command string making it difficult to reconstruct:
{
"--maxEpoch"
"--satEpoch"
"50"
"somestring"
[-1] : "luajit"
[0] : "examples/neuralnetwork.lua"
}
If I can save the exact string to a file from within Lua, I can easily call it again later.
#peterpi is correct that the shell is interpreting the command and as a result stripping away the quotes. However, reconstructing the command exactly is not really necessary to have the shell interpret the command the same way as before.
For simple cases concatenating the arguments to the script is often enough:
local command = table.concat(arg, ' ', -1, #arg)
This will fail if the quotes are actually necessary, most commonly when an argument contains a space or shell character, so quoting everything is easy and somewhat more robust, but not pretty.
Here is an example with a Lua pattern to check for special (bash) shell characters and spaces to decide if and which quotes are necessary. It may not be complete but it handles filenames, most strings, and numbers as arguments.
local mod_arg = { }
for k, v in pairs(arg) do
if v:find"'" then
mod_arg[k] = '"'..v..'"'
elseif v:find'[%s$`><|#]' then
mod_arg[k] = "'"..v.."'"
else
mod_arg[k] = v
end
end
local command = table.concat(mod_arg, ' ', -1, #mod_arg)
print(command)
No doubt somebody will prove me wrong, but generally I don't think this is possible. It's the shell rather than luajit that takes the quotes away and chops the line up into individual tokens.

Resources