Error in manipulating sting with "\" in Lua - lua

local filepath = "c:\\temp\\parentdir"
local dirname = string.match(filepath, "[^\\]+$")
print(dirname)
Above code is giving correct output: parentdir
Then if I use same code but only single "\" as below
local filepath = "c:\temp\parentdir"
local dirname = string.match(filepath, "[^\\]+$")
print(dirname)
I'm getting this error
"lua: main.lua:1: invalid escape sequence near '"c: emp\p'"
please help. How we can solve this issue programatically

It isn't a issue, becaouse you not provide c:\temp\parentdir literally, but c:{tab}emp{unknown_character}arentdir. To provide c:\temp\parentdir you can use:
"c:\\temp\\parentdir"
'c:\\temp\\parentdir'
[[c:\temp\parentdir]]
If you read c:\temp\parentdir from file or input you not have to add second \, because this is only in code escape character. More about here.
Second solution is to use / instead \.

Related

Using io.tmpfile() with shell command, ran via io.popen, in Lua?

I'm using Lua in Scite on Windows, but hopefully this is a general Lua question.
Let's say I want to write a temporary string content to a temporary file in Lua - which I want to be eventually read by another program, - and I tried using io.tmpfile():
mytmpfile = assert( io.tmpfile() )
mytmpfile:write( MYTMPTEXT )
mytmpfile:seek("set", 0) -- back to start
print("mytmpfile" .. mytmpfile .. "<<<")
mytmpfile:close()
I like io.tmpfile() because it is noted in https://www.lua.org/pil/21.3.html :
The tmpfile function returns a handle for a temporary file, open in read/write mode. That file is automatically removed (deleted) when your program ends.
However, when I try to print mytmpfile, I get:
C:\Users\ME/sciteLuaFunctions.lua:956: attempt to concatenate a FILE* value (global 'mytmpfile')
>Lua: error occurred while processing command
I got the explanation for that here Re: path for io.tmpfile() ?:
how do I get the path used to generate the temp file created by io.tmpfile()
You can't. The whole point of tmpfile is to give you a file handle without
giving you the file name to avoid race conditions.
And indeed, on some OSes, the file has no name.
So, it will not be possible for me to use the filename of the tmpfile in a command line that should be ran by the OS, as in:
f = io.popen("python myprog.py " .. mytmpfile)
So my questions are:
Would it be somehow possible to specify this tmpfile file handle as the input argument for the externally ran program/script, say in io.popen - instead of using the (non-existing) tmpfile filename?
If above is not possible, what is the next best option (in terms of not having to maintain it, i.e. not having to remember to delete the file) for opening a temporary file in Lua?
You can get a temp filename with os.tmpname.
local n = os.tmpname()
local f = io.open(n, 'w+b')
f:write(....)
f:close()
os.remove(n)
If your purpose is sending some data to a python script, you can also use 'w' mode in popen.
--lua
local f = io.popen(prog, 'w')
f:write(....)
#python
import sys
data = sys.stdin.readline()

lua table string concat not correct

I have a simple function to read lines from .txt file:
function loadData(file_name, root_path)
-- here, file_name is './list.txt', path is '../data/my/'
for line in io.lines(file_name) do
local data = {}
base_path = root_path .. line
-- so, base_path is something like ../data/my/001
data.file = base_path .. '_color.png'
print(data)
end
end
I expect the data should be {file: "../data/my/001_color.png"}, but I got {_color.png" ../data/my/001}
Can anyone help me? Thanks!
Check your ./list.txt file content for EOL (end of line) as it may be produced on windows (EOL=CR LF) an interpreted on linux (EOL=LF). io.lines takes CR character into line string on linux!
Your programm makes everything correct, but your data is not.
Let assume your first line in ./list.txt is ../data/my/001\r\n
line variable is ../data/my/001\r (print(#line) gives 15 instead of 14 ).
Carriage return (CR) in print moves cursor to start line position witout changing line.
Your print output in this case is something simmilar to {file: "../data/my/001\r_color.png"} (as it depends on print implementation) and you get output:
{file: "../data/my/001
_color.png"} <-- on the same line
Let's combine it:
_color.png"}ata/my/001
To correct this:
provide file without CR (works correctly on all systems)
add in loop on first row: line = line:gsub('[\r\n]','') to remove CR LF

JavaScript: Escape (encode?) special characters in filenames

I have a JavaScript that runs an external program (mediainfo) on local files. However, some of my files have characters that mess up my code.
The code:
objMedInfo = JSON.parse(proc.execSync('mediainfo "' + currentfilename + '" --output=JSON').toString());
The problem is that if currentfilename contains a quotation mark or some other extended characters, the command fails.
Is there a way to escape or encode currentfilename to prevent this? It's not feasible to rename all the potential files.
Use execFileSync instead of execSync. This allows you to supply the arguments in an array, rather than putting everything in a string that has to be parsed by the shell.
objMedInfo = JSON.parse(proc.execFileSync('mediainfo', [currentfilename, '--output=JSON']).toString());

Read Files Using Lua by Directory Using Command Prompt

I was trying to read a .txt file using lua in command prompt, I'm using 'Lua For Windows' but in the way I tried it's not working, it don't give me any error, it don't return anything, not even 'nil'.
I tried this:
file = io.open("C:\Users\user\Desktop\a.txt", "r") --(and my user's name)
io.input(file)
print(io.read())
io.close(file)
The backslash is an escape character in Lua quoted strings.
Try "C:\\Users\\user\\Desktop\\a.txt".
Or avoid the issue using long strings: [[C:\Users\user\Desktop\a.txt]].

Lua: Pattern match after a string?

For example, I have arbitrary lines in this format:
directory C:\Program Files\abc\def\
or something like.
log-enabled On
I want to be able to extract the "C:\Program Files\ab\def\" part out of that first line. Likewise, I want to extract the "On" out in the second line. The spaces between the variable and its value are arbitrary. I will know the name of the variable, but I need extract the value based on that.
So basically, I want to remove the first word and a number of arbitrary spaces that follow the first word, and return what remains until the end of the line.
Assuming that, by "word" you mean "a string of characters without spaces", you can do this:
for line in ioFile:lines() do
local variable, value = line:match("(%S+)%s+(.+)")
... --Do stuff with variable and value
end
One alternative with string.match was shown by Nicol Bolas, here is another alternative:
function splitOnFirstSpace(input)
local space = input:find(' ') or (#input + 1)
return input:sub(1, space-1), input:sub(space+1)
end
Usage:
local command, param = splitOnFirstSpace(line)
If no argument is given (splitOnFirstSpace('no-param-here')), then param is the empty string.
I do not believe Lua is packaged with a split() function like Ruby or Perl.
I found that this guy built a lua version of Perl's split function:
http://lua-users.org/lists/lua-l/2011-02/msg01145.html
If you can guarantee that the argument will only have 1 word before it, with that word not containing any spaces, you can read in that line, run the split function on it, and use the return array's 1 index value as what you want.
You could error check that too and make sure you get a 'C:\' within your expected directory, or check to make sure the string is == to 'On' or 'Off'. Because of using the hardcoded index value I really advocate you error check your expected value. Nothing is worse than having an assumed value be wrong.
If an error is detected make sure to log or print it to the screen so you know about it.
This could catch bugs where maybe the string that was input is improper.
Some simple code that models what I suggest you do:
line = "directory C:\Program Files\abc\def/";
contents = line.split(" "); --Split using a space
directory = contents[2]; --Here is your directory
if(errorCheckDir(directory))
--Use directory
end
EDIT:
In response to comments below Lua indeed begins indexing at 1, not 0.
Also, in the case that the directory contains spaces (which is probable) instead of simply using contents[2], I would loop through all of contents except index 1, and piece back together the directory making sure to add the required space between each index that you attach.
So in the case above, contents[2] and contents[3] would have to be stitched back together with a space in between to recover the proper directory.
directory = contents[2].." "..contents[3]
This can be easily automated using a function which has a loop in it and returns back the proper directory:
function recoverDir(contents)
directory = "";
--Recover the directory
for i=2, table.getn(contents) do
directory = directory..contents[i].." ";
end
--strip extra space on the end
dirEnd = string.len(directory);
directory = string.sub(directory,1,dirEnd-1);
return directory; --proper directory
end

Resources