I/O#

The io library is Lua’s stdio surface, files and streams. string and string.format are the formatting surface. os covers process environment, time, and exit. Together they cover everything it does between standard input, standard output, and the filesystem.

For networking I/O, see Networking. For CLI argument handling, see CLI.

Files#

io.open(path, mode) returns a file handle on success and nil, err on failure. Modes are the usual "r", "w", "a", "r+", "w+", "a+", plus "b" suffix for binary on Windows.

local f, err = io.open("/etc/hostname", "r")
if not f then error(err) end
local host = f:read("*l")            -- one line
f:close()
print(host)

Read modes for f:read.

Mode

What it reads

"*a" / "a"

rest of the file as one string

"*l" / "l"

next line, without the trailing newline

"*L" / "L"

next line, with the trailing newline

"*n" / "n"

next number

n (an integer)

up to n bytes

Lua 5.3+ accepts the modes without the leading *; older versions need the asterisk.

Line iteration#

io.lines(path) and f:lines() return an iterator the operator drives with for. Both close the file automatically when the iterator runs out.

for line in io.lines("/var/log/syslog") do
  if line:find("error") then print(line) end
end

local f = io.open("input.csv")
for line in f:lines() do
  handle(line)
end
f:close()

Writing#

io.write writes to stdout; f:write writes to a file handle. Neither appends a newline; print does.

io.write("hello, ", "world\n")

local f = assert(io.open("out.txt", "w"))
f:write("count=", 42, "\n")
f:close()

For buffered writes the operator flushes explicitly with f:flush() or sets line-buffered mode with f:setvbuf("line").

Standard streams#

io.stdin, io.stdout, io.stderr are pre-opened file handles. io.read() reads from stdin; io.write() writes to stdout.

for line in io.stdin:lines() do
  io.stdout:write(line:upper(), "\n")
end

io.stderr:write("debug: ", tostring(x), "\n")

Formatting#

string.format is the operator’s printf. Format specifiers follow C: %d (integer), %f (float), %s (string), %q (string in a form Lua can read back), %x / %X (hex), %% (literal percent).

print(string.format("%-10s %5d %.2f%%", "cpu", 12, 12.345))
print(string.format("%q", 'with "quotes"'))   --> "with \"quotes\""

The :format method on strings is the same call with sugar.

print(("%s=%d"):format("port", 8080))

Patterns#

Lua patterns are a tiny regex dialect. They are not POSIX or PCRE; they are smaller, faster, and the operator who knows them matches anything the stdlib needs to match. For real regex, reach for lrexlib (see Libraries).

Class

Matches

%a

letters

%d

digits

%s

whitespace

%w

alphanumeric

%p

punctuation

%l, %u

lower, upper

%A, %D, %S, %W

the negation of each

.

any char

[set]

a character class

*, +, -, ?

quantifiers (- is non-greedy)

^, $

anchors

string.find, string.match, string.gmatch, and string.gsub all take patterns.

for ip in ("a 1.2.3.4 b 5.6.7.8"):gmatch("%d+%.%d+%.%d+%.%d+") do
  print(ip)
end

local k, v = ("port=8080"):match("(%w+)=(%w+)")
print(k, v)                            --> port  8080

local s, n = ("foo bar baz"):gsub("%a+", "<%0>")
print(s, n)                            --> <foo> <bar> <baz>  3

Filesystem and process#

os.getenv, os.time, os.date, os.exit cover the process surface. os.execute and io.popen shell out; os.tmpname and os.rename move files. For directory traversal and stat, reach for luafilesystem (lfs) or luaposix.

print(os.getenv("HOME"))
print(os.date("%Y-%m-%d %H:%M:%S"))

local p = io.popen("ls -1", "r")
for line in p:lines() do print(line) end
p:close()

References#