←前
目次
次→

Luaスクリプト機能

$Date: 2024/04/01 13:51:38 $

ライブラリ関数

ヤマハルーターのLuaスクリプトで利用できるライブラリ関数について説明します。標準のLua言語にあってもヤマハルーターでは利用できない関数は、ここに掲載していません。

それぞれの書式の中で、点線で囲まれた部分は省略可能であることを示します。

インデックス

assert
collectgarbage
dofile
each
error
getfenv
getmetatable
ipairs
load
loadfile
loadstring
module
next
pairs
pcall
print
rawequal
rawget
rawset
require
select
setfenv
setmetatable
tonumber
tostring
type
unpack
xpcall
_G
_VERSION
_RT_LUA_VERSION
_RT_LUA_VERSION_NUM
_RT_FIRM_REVISION
_RT_MATH_RANDOM_STATE
arg
string.byte
string.char
string.dump
string.find
string.format
string.gmatch
string.gsub
string.len
string.lower
string.match
string.regexp
string.rep
string.reverse
string.split
string.sub
string.upper

table.concat
table.insert
table.maxn
table.remove
table.sort

math.abs
math.fmod
math.max
math.min
math.random
math.randomseed
io.close
io.flush
io.input
io.lines
io.open
io.output
io.read
io.type
io.write

file:close
file:flush
file:lines
file:read
file:write

bit.band
bit.btest
bit.bor
bit.bxor
bit.bnot
bit.bshift
bit.brotate
rt.command
rt.mail
rt.sleep
rt.syslog
rt.syslogwatch

rt.hw.open
hwd:close
hwd:tone
hwd:on
hwd:blink
hwd:off
hwd:read
hwd:getc
hwd:getchar
hwd:gets

rt.httprequest

rt.socket.tcp
rt.socket.udp
rt.socket.select
rt.socket.dns.toip
rt.socket.dns.tohostname
rt.socket.dns.gethostname
rt.socket.sleep
rt.socket.gettime
rt.socket.newtry
rt.socket.protect
rt.socket.skip
rt.socket._VERSION

tcp:accept
tcp:bind
tcp:listen
tcp:close
tcp:connect
tcp:getpeername
tcp:getsockname
tcp:getstats
tcp:receive
tcp:send
tcp:setoption
tcp:setstats
tcp:settimeout
tcp:shutdown
udp:close
udp:getpeername
udp:getsockname
udp:receive
udp:receivefrom
udp:send
udp:sendto
udp:setpeername
udp:setsockname
udp:settimeout

rt.mime.b64
rt.mime.dot
rt.mime.eol
rt.mime.qp
rt.mime.qpwrp
rt.mime.unb64
rt.mime.unqp
rt.mime.wrp

os.clock
os.date
os.difftime
os.exit
os.getenv
os.remove
os.rename
os.time

package.seeall

coroutine.create
coroutine.resume
coroutine.running
coroutine.status
coroutine.wrap
coroutine.yield

基本関数

assert(value , message)

valueが偽、つまり、nilfalseの場合にはエラーを発行し、スクリプトの実行を停止します。その他の場合は戻り値として引数をすべて返し、スクリプトの実行が継続されます。messageエラーの場合に表示される文字列であり、省略した場合は"assertion failed!"という文字列が表示されます。

function f(x,y)
  assert(type(x) == "string") -- 引数が文字列型であることをチェックする
  assert(y > 0 and y < 100, "y is out of range") -- 引数の値の範囲をチェックする
  …
end

collectgarbage(opt , arg)

この関数はガベージコレクション動作を制御します。optに与える文字列で以下のような動作をします。

dofile(filename)

filenameで指定されたファイルを読み出し、Luaスクリプトとして実行します。

標準のLua言語と異なり、filenameは省略できません。

each(arg...)

この関数は標準のLua言語には存在しません。_RT_LUA_VERSION"1.03"以降のファームウェアで使用することができます。

戻り値としてイテレータ関数を返す関数で、一般for文とともに用いることで、引数を巡回することができます。

特殊なケースとして、引数が一つだけでテーブル型の場合は、その引数を配列とみなして先頭から順に要素を巡回します。

for v in each(1, 2, "a", "b") do
  print(v)
end
t = {1, 2, "a", "b"}
for v in each(t) do
  print(v)
end
    

error(message , level)

messageをエラーメッセージとして表示し、Luaスクリプトの実行を停止します。この関数は呼び出し元には戻りません。

levelでは、エラーの発生場所として表示する行番号を制御できます。levelを省略した場合、あるいは1を与えた場合には、error関数を呼び出した行がエラーの発生場所となります。2を与えた場合には、error関数を呼び出している関数を呼び出した行がエラーの発生場所となります。以降、3、4と値が増えるにつれ、関数の呼び出し関係が深くなっていきます。0を与えると、エラーの発生行を表示しません。

function f1(x) f2(x) end
function f2(x) f3(x) end
function f3(x) f4(x) end
function f4(x)
  if x == 1 then
    error("", 1)       -- f4()でエラー
  elseif x == 2 then
    error("", 2)       -- f3()でエラー
  elseif x == 3 then
    error("", 3)       -- f2()でエラー
  elseif x == 4 then
    error("", 4)       -- f1()でエラー
  else
    error("", 5)       -- トップレベルでエラー
  end
end
    

getfenv(func)

funcが関数のときは、その関数の環境を返します。

funcが数値のときは、その値をスタックレベルとみなし、環境を返す関数を指定します。すなわち、以下のようになります。

funcが0のときは、グローバル環境を返します。funcを省略したときには、1が与えられたものとします。

getmetatable(object)

objectがメタテーブルを持たない場合はnilを返します。objectがメタテーブルに"_metateble"をキーとする要素を持つ場合には、その要素の値を返します。その他の場合には、objectのメタテーブルを返します。

ipairs(table)

戻り値として、(イテレータ関数、table、0)の三つ組みを返す関数で、一般for文とともに用いることで、テーブルの中で数値(FIXNUM)をキーとする要素を巡回することができます。

以下の例では、テーブルtの数値キーと値、(1, t[1])(2, t[2])、…を順にprintで表示します。

for i, v in ipairs(t) do
  print(i, v)
end
    

ipairs配列を対象とする関数なので、文字列等、数値(FIXNUM)以外をキーとする要素は取り出せません。また、0、負の数をキーとする要素も取り出せません。すべての要素を取り出すには、pairs関数を使用します。

load(func , chunkname)

関数funcを用いてチャンクをロードします。funcは呼び出されるたびに文字列を返す関数です。funcが空文字列、nilのいずれかを返すか、あるいは何も返さなかったらそこでチャンクは終了したものとみなされ、それまで返された文字列をすべて連結、コンパイルした関数がloadの戻り値として返されます。チャンクのコンパイルでエラーが発生したときには、nilとエラーメッセージ文字列が返されます。

chunknameはチャンクの名前としてエラーメッセージやデバッグ情報として用いられます。省略したときには、"=(load)"が用いられます。

loadfile(filename)

ファイルfilenameからチャンクを読み出し、関数を返します。戻り値等はloadと同様です。

標準のLua言語ではfilenameが省略できますが、ヤマハルーターの実装ではfilenameは省略できません。

loadstring(string , chunkname)

文字列stringをチャンクとみなし、関数を返します。戻り値、chunknameの意味等はloadと同様です。

以下の例は、文字列で与えられたチャンクをロードし、実行するときの常套句です。

assert(loadstring(str))()
    

loadstring(str)で文字列strをコンパイルし、関数にします。assertを使うのは、strエラーがあった場合にそれを捕まえるためです。最後のカッコ()で、コンパイルされた関数を実行しています。

next(table , key)

テーブルtableで、keyをキーとする要素の次の要素のキーと値を返します。keyが省略されるか、nilが与えられたときには、最初の要素のキーと値を返します。keyをキーとする要素がテーブルの最後の要素であったときには、nilを返します。

next(t) == nilであれば、tはまったく要素を持たないテーブルです。これは、テーブルが空かどうかを検査するときに使えるテクニックです。

テーブル内の要素の順番は規定されていません。キーが数値の場合でも、nextで巡回する順序はやはり規定されていません。そのため、nextでどのような順序で要素が返されるかは予想できません。数値のキーに対して数値順でアクセスしたいときにはipairsを用います。

nextを順に呼び出している途中で、テーブルに新しい要素を追加したときには、次のnextの動作は不定となります。すでに存在している要素の値を変更することは問題ありません。また、要素を削除することも問題はありません。

pairs(table)

戻り値として、(nexttable、nil)の三つ組みを返す関数で、一般for文とともに用いることで、テーブルの要素を巡回することができます。

以下の例では、テーブルtのすべての要素のキーと値をprintで表示します。

for k, v in pairs(t) do
  print(k, v)
end
    

pairsを呼び出している間にテーブルに変更を加えるときの注意点は、nextを参照してください。

pcall(func, ...)

関数funcを、保護されたモードで呼び出します。残りの引数は、fを呼び出すときの引数です。

通常は関数の実行中にエラーが発生するとスクリプト全体が停止しますが、保護されたモードでは、funcの実行中にエラーが発生しても、スクリプト全体は停止せず、pcallの戻り値としてエラーの発生状況を通知します。

pcallの最初の戻り値がtrueであったときは、funcの実行中にエラーは発生していません。pcallは残りの戻り値として、funcの戻り値を返します。

pcallの最初の戻り値がfalseであったときは、funcの実行中にエラーが発生しています。2番目の戻り値はエラーメッセージです。

print(...)

任意の数の引数を受け取り、それをコンソールに出力し、最後に改行します。引数はtostring関数により文字列表現に変換されます。

print関数の出力フォーマットを制御する方法はありません。フォーマットを制御しながら出力したい場合には、string.format関数とio.write関数を組み合わせて使用します。

rawequal(value1, value2)

メタメソッドを用いずに、value1とvalue2を比較します。trueまたはfalseを返します。

rawget(table, key)

メタメソッドを用いずに、テーブルtablekeyをキーとする要素の値(table[key])を返します。

rawset(table, key, value)

メタメソッドを用いずに、テーブルtablekeyをキーとする要素(table[key])に値valueを代入します。関数の戻り値はtableです。

select(num, ...)

numの値が1以上の数値Nのときには、残りの引数の先頭からN番目以降の引数をすべて返します。numが文字列"#"であったときは、残りの引数の数を返します。

select(3, "a", "b", "c", "d")    ⇒ "c", "d"
select("#", "a", "b", "c", "d")  ⇒ 4
    

selectは、関数の可変数引数を扱うときに使用すると便利です。以下の例では、可変数引数を持つ関数fの引数を一つずつ、関数gの引数として渡しています。

function f(...)
  for i = 1, select("#", ...) do
    g((select(i, ...)))
  end
end
    

setfenv(func, table)

funcが関数のときは、tableをその関数の環境として設定します。

funcが数値のときは、その値をスタックレベルとみなし、環境を返す関数を指定します。すなわち、以下のようになります。

funcが0のときは、グローバル環境を設定します。funcを省略したときには、1が与えられたものとします。

setfenvの戻り値は環境を設定した関数になります。グロバール環境を設定した場合には、戻り値はありません。

setmetatable(table, metatable)

テーブルtableにメタテーブルmetatableを設定します。metatablenilの場合には、tableからメタテーブルを削除します。いずれの場合も、テーブルtableがもともとメタテーブルを持っていて、そのメタテーブルが__metatable要素を持っている場合にはエラーになります。

tonumber(value , base)

valueを数値に変換します。valueが数値型であれば、そのままの値を返します。valueが文字列型であり、数値の文字列表現とみなせるものであれば、その数値を返します。その他の場合はnilを返します。

baseは文字列を数値に変換するときの基底数であり、2から36までが指定できます。たとえば、baseが2であれば文字列は2進数と解釈され、10であれば10進数、16であれば16進数と解釈されます。baseを省略したときには基底数は10とします。

baseが指定され、10もしくは16以外の数である場合は、関数の戻り値は-2147483648〜2147483647の範囲内にある必要があります。baseが省略されるか、10または16が指定されている場合には、数値型で表せる任意の数値を戻り値として返せます。

また、文字列の先頭に"0x"がある時には、特別な扱いがされます。この場合、基底数が10であっても、"0x"に引き続く文字列は16進数であると解釈されます。基底数が16の場合も同様に"0x"を除いた部分を16進数と解釈します。基底数が10もしくは16以外のときには、文字列の先頭の"0x"を16進数を示す記号とは解釈しません。よって、基底数が34未満で文字"x"が数値の表現とはならない場合には、"0x"があると数値として解釈できず、nilを返します。

a = tonumber(11)       --- a = 11
a = tonumber("11")     --- a = 11
a = tonumber("11", 2)  --- a = 3
a = tonumber("11", 16) --- a = 17
a = tonumber("0x11")   --- a = 17
    

tostring(value)

valueをそれぞれの型に応じたフォーマットで文字列に変換します。

a = tostring(11)  --- a = "11"
a = tostring(true) --- a = "true"
a = tostring(false) --- a = "false"
a = tostring(nil) --- a = "nil"
a = tostring({}) --- a = "table: 00907590"
    

type(value)

valueの型を文字列で返します。それぞれの型で返される文字列は以下のとおりです。

unpack(table , i , j)

テーブルtableの、キーiからjまでの要素の値を複数値として返します。ijより大きい場合には何も返しません。該当するキーに値がないところはnilが返ります。

iを省略した場合は1、jを省略した場合は長さ演算子#で定義されるテーブルの要素数になります。

a = { 1, 2, 3 }
print(unpack(a)) --- 1, 2, 3
print(unpack(a, 1, 3)) --- 1, 2, 3
print(unpack(a, 2, 3)) --- 2, 3
print(unpack(a, 3, 3)) --- 3
print(unpack(a, 3, 2)) --- 何も表示されない
print(unpack(a, -1, 2)) --- nil, nil, 1, 2

xpcall(func, handler)

xpcallpcallとよく似ており、エラー処理関数を指定できるところだけが異なります。

xpcallは、handlerをエラー処理関数として関数funcを保護モードで呼び出します。funcの実行中にエラーが発生した場合には、handlerが呼び出されます。

xpcallの最初の戻り値がtrueだった場合には、funcの実行中にエラーは発生していません。xpcallの2番目以降の戻り値としてfuncの戻り値が返されます。

xpcallの最初の戻り値がfalseだった場合には、funcの実行中にエラーが発生し、handlerが呼び出されています。xpcallの2番目以降の戻り値はhandlerの戻り値です。

グローバル変数

定義済みのグローバル変数を列挙します。

変数名説明値の例
_G グローバル環境のコピーが保存されています。Lua自身はこの変数を使用していないため、この関数を操作しても環境にはまったく影響は与えません。環境を変更するときには、setfenvを使用します。 グローバル環境のコピー(テーブル型)
_VERSION Lua言語のバージョン番号を表す文字列。 "Lua 5.1"
_RT_LUA_VERSION ヤマハルーターでのLuaスクリプト機能のバージョン番号を表す文字列。 "1.0"
_RT_LUA_VERSION_NUM _RT_LUA_VERSIONの数値表現。 100
_RT_FIRM_REVISION ヤマハルーターのファームウェアリビジョンを表す文字列。 "RTX1200 Rev.10.01.12 (Fri Jul 31 17:52:51 2009)"
_RT_MATH_RANDOM_STATE math.random()関数のための内部状態を表すユーザーデータ。_RT_LUA_VERSION"1.01"以降のファームウェアで定義されています。
arg luaコマンドで渡された引数の文字列を格納するテーブル。

文字列操作

string.byte(str, i, j)

文字列stri文字目からj文字目までの文字を、それぞれ内部文字コードの数値に変換し、複数値として返します。

文字列の先頭は1文字目であり、iを省略したときには1となります。jを省略したときには、iと同じ値、つまり、戻り値はi文字目の1文字だけとなります。

ヤマハルーターのLuaスクリプトでは、文字列の内部コードはASCIIおよびシフトJISです。

a, b = string.byte("ab", 1, 2) -- a=97, b=98
a, b = string.byte("ab")       -- a=97, b=nil
a, b = string.byte("ab", 2)    -- a=98, b=nil
a, b = string.byte("あ", 1, 2) -- a=130, b=160
    

string.char(...)

与えられた引数の数と同じ長さの文字列で、それぞれの文字は対応する引数の値を内部コードとする文字となっているものを返します。引数は、0個以上の数値(FIXNUM)でなくてはなりません。引数が0個のときは長さ0の文字列を返します。

ヤマハルーターのLuaスクリプトでは、文字列の内部コードはASCIIおよびシフトJISです。

s = string.char(97, 98)   -- s = "ab"
s = string.char(130, 160) -- s = "あ"
s = string.char()         -- s = ""
    

string.dump(func)

与えられた関数のバイナリ表現を含む文字列を返します。この文字列は、loadstringの引数として与えることができ、その場合、関数のコピーを得ることができます。関数は上位値を持たないLua関数である必要があります。

string.find(str, pattern, init, plain)

文字列strの先頭から、パターンpatternに合致する部分を探します。合致する部分が見つかったときには、文字列の先頭が1として、その部分の先頭、最後の位置の2つの数値を戻り値として返します。合致する部分が見つからないときにはnilを返します。

また、patternキャプチャを持っている場合には、キャプチャされた文字列は、位置を表す2つの数値に続く戻り値として返されます。

3つ目の引数initを指定した場合には、パターンpatternを探し始める場所を先頭ではなく、init文字目から始めることができます。initには負の数も指定でき、その場合は末尾から何文字目、という形になります。

4つめの引数plaintrueを指定した場合には、patternパターンではなく単なる文字列であると解釈されます。したがって、patternに単純に一致する部分を探すようになります。

patternが正規表現オブジェクトで、かつplaintrueの場合にはnilを返します。

a, b = string.find("ABCDE", "BC")        -- a=2, b=3
a, b = string.find("ABCDE", "%a*")       -- a=1, b=5
a, b = string.find("ABCDE", /\a*/)       -- a=1, b=5
a, b = string.find("あいうえお", "いう") -- a=3, b=6
a, b, c = string.find("ABCDE", "B(.)D")  -- a=2, b=4, c="C"
    

string.format(format, ...)

引数の値を文字列formatの指示に従い整形した文字列を返します。C言語のsprintf関数によく似た関数です。

formatは、残りの引数を文字列に変換するための変換指示句を含む文字列です。変換指示句は、パーセント%で始まり、変換指示子(dxXcsq%z)で終わります。変換指示句によって出力される文字列のことをフィールドと呼びます。パーセントと変換指示子の間には、フラグ、フィールド幅、精度をこの順で置いてもよいことになっています。

string.formatは、formatを読み出しながら、その指示に従いフィールドを生成していきます。変換指示句ではない文字は、そのまま出力されます。

formatに変換指示句があったときには、対応する順番の引数を読み出し、変換指示句の指示通りの文字列に変換して出力します。変換指示句はそれぞれ特定の型の引数を要求し、それ以外の型の引数が与えられたときはエラーとなります。

フラグは、引数の変換の仕方を指定します。以下のフラグが使用できます。

#
o変換の場合、出力結果の先頭が必ず0になるよう、必要であれば先頭に0が補われます。x、X変換の場合には、値が0でなければ先頭に0xまたは0Xが補われます。
0
数値の変換(d、x、X)の場合に、変換した値の左側を空白文字ではなく0で埋めます。フラグ0とフラグ-が同時に指定された場合には、フラグ0は無視されます。
-
変換した文字列を、フィールドの中で左揃えにします。このフラグが指定されていない場合には右揃えとなります。

フィールド幅は、変換後の文字列を出力する最小の幅を10進数の数値で指定します。変換後の文字列長がフィールド幅より短い場合は文字列の左側(フラグ-が指定された場合は右側)が空白文字または0で埋められます。文字列長がフィールド幅より長い場合には、文字列は切り詰められずそのまま出力されます。

精度は、ピリオド.とそれに続く10進数という形で指定します。数値の変換(d、x、X)の場合には、出力される最小の桁数を指定します。文字列変換(s)の場合には、文字列から出力される最大文字数を指定します。

変換指示子には以下の種類があります。

d
数値型の引数を、10進表記に変換します。
負数の場合は先頭にマイナス-を追加します。
x、X
数値型の引数を、16進表記に変換します。
xの場合はabcdefを、Xの場合はABCDEFを使用します。
負数の場合は、4294967296(10進)を加算した正数として表示します。
c
数値型の引数を、その値を256で割った余りを内部コードとする文字に変換します。
s
文字列型の引数を、文字列の先頭から終端まで出力します。精度が指定されている場合には、その文字数だけが出力されます。
q
文字列型の引数を、文字列の先頭から終端まで出力します。そのときに、Lua言語のインタプリタが読み出せる形に、ダブルクォート、改行、NUL文字、バックスラッシュが適切にエスケープされます。
%
文字%を出力します。変換される引数はありません。フラグ、フィールド幅、精度を指定してはならず、変換指定句全体は必ず%%という形になります。
s = string.format("%d, %x", 10, 10)                    -- s="10, a"
s = string.format("%dab%d", 10, 20)                    -- s="10ab20"
s = string.format("[%4d], [%-4d], [%04d]", 10, 10, 10) -- s="[  10], [10  ], [0010]"
    

string.gmatch(str, pattern)

文字列strに対して、呼び出されるごとにパターンpatternキャプチャを順に返すイテレータ関数を返します。パターンにキャプチャが含まれていないときには、イテレータ関数の戻り値はパターンに合致する文字列全体となります。

string.gmatchは一般for文とともに使うことで、文字列から条件に合う部分を次々に抜き出して処理することができます。

以下の例では、文字列から単語を抜き出し、1行に一つずつ表示しています。

s = "hello world from Lua"
for w in string.gmatch(s, "%a+") do
  print(w)
end
    

また、次の例では、key=value形式の文字列を探し、テーブルtにそれを設定しています。

t = {}
s = "from=world, to=Lua"
for k, v in string.gmatch(s, "(%w+)=(%w+)") do
  t[k] = v
end
    

string.gsub(str, pattern, repl, n)

文字列strに対して、パターンpatternに合致する部分をすべて引数replの指示通りに置き換えた新しい文字列と、patternが見つかった数を返します。文字列strは一切変更されません。

4番目の引数nを指定した場合には、置き換えは最初のn個だけ実行されます。省略した場合は、見つかった置き換えはすべて実行されます。

replが文字列型の場合、replそのものが置き換え文字列となります。replの中の以下の文字列は特別な意味を持ちます。

%0
patternに合致する部分全体を表わす。
%1〜%9
patternの中の、指定した順番のキャプチャに合致する文字列を表わす。
%%
パーセント文字そのものを表わす。

replがテーブル型の場合、pattern中の最初のキャプチャをキーとするreplの要素の値が置き換え文字列となります。patternキャプチャを含まない場合、patternに合致する部分全体がキーとなります。

replが関数型の場合、pattern中のすべてのキャプチャを引数としてreplが呼び出され、その戻り値が置き換え文字列となります。patternキャプチャを含まない場合、patternに合致する部分全体が引数となります。

replがテーブル型もしくは関数型の場合、テーブルの要素の値もしくは関数の戻り値が文字列型であれば、それがそのまま置き換え文字列となります。数値型(FIXNUM)の場合は、文字列に変換したものが置き換え文字列になります。

テーブルの要素の値もしくは関数の戻り値がfalseあるいはnilの場合には、置き換えは実行されず、元の文字列がそのまま残ります。他の値になった場合には、エラーです。

x, y = string.gsub("HELLO world", /o/i, "o")
-- x = "HELLo world", y = 2

x, y = string.gsub("hello world", "(%w+)", "%1 %1")
-- x = "hello hello world world", y = 2

x, y = string.gsub("hello world from Lua", /(\w+)\s*(\w+)/, "%2 %1")
-- x = "world hello Lua from", y = 2

t = { name = "lua", version = "5.1" }
x = string.gsub("$name-$version.tar.gz", "%$(%w+)", t)
-- x = "lua-5.1.tar.gz"

function f(s)
  if s == "hello" then
    return "bye"
  elseif s == "world" then
    return "universe"
  else
    return "unknown"
  end
end
x = string.gsub("hello world", "(%w+)", f) -- x = "bye universe"
    

string.len(str)

文字列strの長さを返します。Lua言語での「文字列の長さ」はバイト長です。空文字列""の長さは0となります。

x = string.len("ABCDE")      -- x = 5
x = string.len("")           -- x = 0
x = string.len("あいうえお") -- x = 10
    

string.lower(str)

文字列str中の英大文字を小文字に変換した文字列を新しく作成し、それを返します。str自体は一切変更されません。

変換対象となるのはASCIIコードの範囲内の英大文字だけです。シフトJISの英大文字は変換されません。

x = string.lower("AB01CD")     -- x = "ab01cd"
x = string.lower("AB01CD") -- x = "AB01CD"
    

string.match(str, pattern, n)

文字列strからパターンpatternに合致する部分を先頭から探し、見つかった場合にはpattern中のキャプチャをすべて返します。patternキャプチャが存在しない場合には、patternに合致する部分全体の文字列を返します。patternに合致する部分が見つからない場合にはnilを返します。

3番目の引数nを指定した場合には、patternstrn文字目から探し始めます。省略した場合は1文字目からとなります。nには負の数も指定でき、その場合は末尾から何文字目、という形になります。

patternが正規表現オブジェクトで、オプションとしてgが指定されているときには、文字列中に見つかった部分で、重複していないものをすべて返します。その他の場合には、最初に見つかった部分だけを返します。

x = string.match("hello world", "%w+")    -- x = "hello"
x = string.match("hello world", " (%w+)") -- x = "world"
x = string.match("hello world", "%w+", 2) -- x = "ello"
x,y,z,w = string.match("hello world", /\w\w/g) -- x = "he", y = "ll", z = "wo", w = "rl"
x = {string.match("hello world", /\w\w/g)} -- x = { "he", "ll", "wo", "rl" }
    

string.regexp(str, option)

この関数は_RT_LUA_VERSION"1.03"以降のファームウェアで使用することができます。

文字列str正規表現とみなして、それに対応する正規表現オブジェクトを返します。正規表現オブジェクトは、string.find関数やstring.match関数、string.gmatch関数、string.gsub関数、string.split関数、rt.syslogwatch関数のパターンとして利用できます。

文字列に正規表現として誤りがある場合は、nilとエラー文字列を返します。

文字列optionは、正規表現のコンパイルオプションを指定します。optionは以下の文字の組み合わせで指定します。

上記以外の文字がoptionに含まれていた場合は、正規表現オブジェクトが利用されるときのオプションとなります。

string.regexp関数は、正規表現糖衣構文として記述することで呼び出すことも可能です。
x = string.regexp("hello", "i")
x = /hello/i
    

string.rep(str, n)

文字列strn個、連結した文字列を返します。

x = string.rep("ab", 5) -- x = "ababababab"
    

string.reverse(str)

文字列strを逆順にした文字列を返します。なお、シフトJISの文字列を指定することはできません。

x = string.reverse("hello world") -- x = "dlrow olleh"
    

string.split(str, pattern, n)

この関数は_RT_LUA_VERSION"1.03"以降のファームウェアで使用することができます。

文字列strを、パターンpatternに合致する部分で分割したものを返します。返される文字列群に、patternに合致する部分は含まれません。

4番目の引数nを指定した場合には、分割は最初のn回だけ実行されます。省略した場合は、見つかった分割はすべて実行されます。

x = { string.split("hello world", /\s+/) } -- x = { "hello", "world" }

str = "hello world"
for w in each(str:split(/\s+/)) do
    print(w)
end
    

string.sub(str, i, j)

文字列stri文字目からj文字目までの部分文字列を返します。ijには負の数を指定することもでき、その場合は末尾から何文字目、という形になります。jを省略した場合には-1、つまりstrの末尾までとなります。

x = string.sub("ABCDE", 2, 4)  -- x = "BCD"
x = string.sub("ABCDE", 3)     -- x = "CDE"
x = string.sub("ABCDE", 2, -2) -- x = "BCD"
x = string.sub("ABCDE", -2)    -- x = "DE"
    

string.upper

文字列str中の英小文字を大文字に変換した文字列を新しく作成し、それを返します。str自体は一切変更されません。

変換対象となるのはASCIIコードの範囲内の英小文字だけです。シフトJISの英小文字は変換されません。

x = string.upper("ab01cd")     -- x = "AB01CD"
x = string.upper("ab01cd") -- x = "ab01cd"
    

パターン

パターンは、string.match関数などで文字列を検索するために使用されるものです。Lua独自のパターンと正規表現が利用できます。

正規表現は_RT_LUA_VERSION"1.03"以降のファームウェアで扱うことができます。

パターンは、特別な意味を持つ特殊文字と、それ以外の通常文字から構成されます。通常文字は、それ自身に合致します。たとえば、aは、a自身に合致します。特殊文字を含まないパターンは、その文字列そのままが対象文字列中から検索されます。

パターンで使用する特殊文字は以下のとおりです。

Luaパターン正規表現説明補足
^\A 文字列の先頭に合致します。
^ 文字列の先頭に合致します。 mオプションが指定された場合は、改行文字の直後にも合致します。
$\z 文字列の末尾に合致します。
$ 文字列の末尾に合致します。文字列の末尾が改行文字の場合はその直前に合致します。 mオプションが指定された場合は、文字列中の改行文字の直前にも合致します。
\Z 文字列の末尾に合致します。文字列の末尾が改行文字の場合はその直前に合致します。
\b 単語の境界に合致します。
\B 単語の境界ではないところに合致します。
\G 最初にパターンが合致した場所に合致します。
\K この文字が現れる前の探索結果は、最終的に報告される探索結果に含めません。
.. 任意の1文字に合致します。
*
-
*
*+
*?
直前の文字が0回以上続く文字列に合致します。 Luaの*、+、?は常にできるだけ長い文字列に合致します。-は常にできるだけ短い文字列に合致します。
正規表現の場合で、繰り返し記号の後ろに何もついていない場合は、デフォルトではできるだけ長い文字列に合致しますが、Uオプションが指定されている場合はできるだけ短い文字列に合致します。
後ろに+がついている場合は、常にできるだけ長い文字列に合致します。
後ろに?がついている場合は、デフォルトではできるだけ短い文字列に合致しますが、Uオプションが指定されている場合はできるだけ長い文字列に合致します。
++
++
+?
直前の文字が1回以上続く文字列に合致します。
??
?+
??
直前の文字が0回もしくは1回現れる文字列に合致します。
{N} 直前の文字が正確にN回現れる文字列に合致します。
{N,M}
{N,M}+
{N,M}?
直前の文字がN〜M回現れる文字列に合致します。
{N,}
{N,}+
{N,}?
直前の文字がN回以上現れる文字列に合致します。
| |の前後のパターンのいずれかに合致する文字列に合致します。
[…][…] 角カッコで囲まれた中にある文字を元とする文字集合であり、文字集合に含まれる任意の1文字に合致します。角カッコの中では、最初の文字と最後の文字をマイナス(-)でつなぐことで文字の範囲を指定することもできます。範囲を指定するときには、最初と最後の文字は同じ種類の文字(数字、英大文字、英小文字)でないといけません。
開き角カッコ([)の直後がキャレット(^)の場合には、文字集合に含まれる文字に合致するのではなく、文字集合に含まれない文字に合致するようになります。したがって、キャレット(^)を文字集合に含みたいときにはそれは先頭にあってはいけません。
閉じ角カッコ(])を集合に含む場合は、必ず最初の開き角カッコの直後におく必要があります。開き角カッコはどこにあってもよいことになっています。
正規表現の場合には、POSIX文字集合も使用できます。
%d\d 数字(0〜9)に合致します。
\D 数字(0〜9)ではない文字に合致します。
%a 英文字(A〜Z、a〜z)に合致します。
%u 英大文字(A〜Z)に合致します。
%l 英小文字(a〜z)に合致します。
%w 英数字(A〜Z、a〜z、0〜9)に合致します。
\w 英数字(A〜Z、a〜z、0〜9)およびアンダースコア(_)に合致します。
\W 英数字(A〜Z、a〜z、0〜9)およびアンダースコア(_)ではない文字に合致します。
%s 空白文字(ASCIIコードで0x09(水平タブ)、0x0a(改行)、0x0b(垂直タブ)、0x0c(改ページ)、0x0d(復帰)、0x20(スペース)の文字)に合致します。
\s 空白文字(ASCIIコードで0x09(水平タブ)、0x0a(改行)、0x0c(改ページ)、0x0d(復帰)、0x20(スペース)の文字)に合致します。
\S 空白文字(ASCIIコードで0x09(水平タブ)、0x0a(改行)、0x0c(改ページ)、0x0d(復帰)、0x20(スペース)の文字)にではない文字に合致します。
\h 水平空白文字(ASCIIコードで0x09(水平タブ)、0x20(スペース)の文字)に合致します。
\H 水平空白文字(ASCIIコードで0x09(水平タブ)、0x20(スペース)の文字)ではない文字に合致します。
\v 垂直空白文字(ASCIIコードで0x0a(改行)、0x0b(垂直タブ)、0x0c(改ページ)、0x0d(復帰)の文字)に合致します。
\V 垂直空白文字(ASCIIコードで0x0a(改行)、0x0b(垂直タブ)、0x0c(改ページ)、0x0d(復帰)の文字)ではない文字に合致します。
%x 数字(0〜9)と英文字のうちA〜F、a〜fに合致します。
%c 制御文字(ASCIIコードで0x00〜0x1f、0xffの文字)に合致します。
%p 区切り文字(!、"、#、$、%、&、'、(、)、*、+、,、-、.、/、:、;、>、=、<、?、@、[、\、]、^、_、`、{、|、})に合致します。
%z NUL文字(ASCIIコードが0x00の文字)に合致します。
%X、ただし、Xは英数字以外 \X、ただし、Xは英数字以外 文字Xそのものに合致します。
\a アラーム(0x07)文字に合致します。
\cX 文字X(Xが英文字の場合は大文字に変換後)のASCIIコードと0xC0の排他的論理和を取った制御文字に合致します。
\e エスケープ(0x1b)文字に合致します。
\f 改ページ(0x0c)文字に合致します。
\n 改行(0x0a)文字に合致します。
\r 復帰(0x0d)文字に合致します。
\t 水平タブ(0x09)文字に合致します。
\DD
\DDD
ASCIIコードが十進数でDD、DDDHである文字に合致します。
\xHH
\x{HH}
ASCIIコードが十六進数でHHである文字に合致します。
\R 改行文字に合致します。以下のパターンと同等です。
(?>\r\n|\n|\x0b|\f|\r|\x85)

%bXY、ただし、X、Yはそれぞれ独立した文字 文字Xで始まり、文字Yで終わる部分文字列に合致します。たとえば、%b()は、カッコで囲まれた部分文字列に合致します。
(…)(…) カッコで囲まれた中にある文字列をグループとして扱います。たとえば、「(abc)+」というパターンは「abc」、「abcabc」、「abcabcabc」など、「abc」という列が1回以上繰り返す文字列に合致します。 カッコはキャプチャとしても使われます。
%1〜%9\1〜\9
\gN
\g{N}
キャプチャされた部分文字列に合致します。数字は正規表現の先頭から数えた、キャプチャの番号を表します。
正規表現の場合、Nは1〜32または-1〜-32です。Nが正の場合は\1等と同じく先頭から数えたキャプチャの番号を表します。Nが負の場合は、その場所から前方に戻る方向に数えたキャプチャの相対的な番号を表します。
string.gsub関数の置き換え文字列中にキャプチャを記述するときには、正規表現の場合でも、%1〜%9を使用します。\1〜\9や\gN、\g{N}、名前による参照は正規表現内だけでの記述方法です。
(?<NAME>…)
(?'NAME'…)
(?P<NAME>…)
キャプチャされる部分文字列に名前(NAME)を付けます。NAMEは最大32文字の英数字とアンダースコアです。名前は、キャプチャを参照するときに利用できます。参照するときには、名前が付けられたキャプチャを番号で指定することもできます。
\k<NAME>
\k'NAME'
\k{NAME}
\g{NAME}
(?P=NAME)
名前(NAME)が付けられたキャプチャを参照します。
() その場所の文字列の位置をキャプチャします。
(?#…) カッコ内をコメントとします。
(?:…) カッコ内をグループ化しますが、キャプチャの対象にはしません。
(?|…) カッコ内をグループ化しますが、キャプチャの対象にはしません。また、カッコ内にある選択(|)ごとに、キャプチャ番号をリセットします。
(?>…) カッコ内をグループ化しますが、キャプチャの対象にはしません。また、カッコ内のパターンに一度合致した文字列は、他のパターンが合致しない場合でも新しい合致パターンを探索するために短縮することはありません。 たとえば、"aab"という文字列は/a*ab/という正規表現には合致しますが、/(?>a*)ab/という正規表現には合致しません。
通常は、a*"aa"に合致しても、正規表現の残りのabが合致しないためa*に合致するパターンを"a"に短縮して残りをやり直しますが、/(?>a*)の場合は、そのような短縮は行わないためです。
(?=…) 探索している位置から先に向かう文字列がカッコ内のパターンに合致するかどうか確認します。合致した場合のみ探索は成功します。 探索された結果にカッコ内の部分は含まれません。キャプチャの対象になりません。
(?!…) 探索している位置から先に向かう文字列がカッコ内のパターンに合致するかどうか確認します。合致しない場合のみ探索は成功します。
(?<=…) 探索している位置より前にある文字列がカッコ内のパターンに合致するかどうか確認します。合致した場合のみ探索は成功します。
(?<!…) 探索している位置より前にある文字列がカッコ内のパターンに合致するかどうか確認します。合致しない場合のみ探索は成功します。
(?…) (?と)の間にオプション文字を記述することで、それ以降の部分でオプションを有効にします。また、ハイフン(-)があると、それ以降に記述されたオプションは無効になります。有効なオプション文字は以下です。
  • i ... 英文字の大文字、小文字を区別しない。
  • s ... 「.」が改行文字の直後にも合致する。
  • x ... 正規表現中の空白文字と「#」から改行までを無視する。
  • m ... 「^」「$」が文字列中の改行文字の前後にも合致する。
  • U ... 「*」「+」などの長さ指定記号ができるだけ短い文字列に合致しようとする。一方、「*?」「+?」などはできるだけ長い文字列に合致しようとする。
(?: )のカッコ内だけでオプションを有効、無効にしたい場合には、?と:の間にオプション文字を記述する方法も使えます。たとえば、以下の二つは同じ意味になります。
(?i:saturday|sunday)
(?:(?i)saturday|sunday)

正規表現の場合は、[…]による文字集合の中で、以下に示すPOSIX文字集合が利用できます。

[:NAME:]とするとNAMEの文字集合となり、[:^NAME:]とすると補集合となります。

集合の名前含まれる文字
alnum英文字と数字
alpha英文字
asciiASCIIコードで0x00〜0x7Fの文字
blank空白(0x20)と水平タブ(0x09)
cntrlASCIIコードで0x00〜0x1fと0x7fの制御文字
digit数字
graph印字可能(ASCIIコードで0x21〜0x7e)文字
lower英小文字
print印字可能(ASCIIコードで0x21〜0x7e)文字と空白(0x20)
punct印字可能(ASCIIコードで0x21〜0x7e)文字から英数字を除いたもの
space空白(0x20)、水平タブ(0x09)、改行(0x0a)、垂直タブ(0x0b)、改ページ(0x0c)、復帰(0x0d)
upper英大文字
word英文字と数字、アンダースコア(_) (\wと同じ)
xdigit数字とA〜F、a〜f

キャプチャ

パターンは、カッコで囲まれたサブパターンを含むことができ、これをキャプチャと呼びます。パターンが合致したときには、キャプチャに相当する部分文字列は保存され、後で使用することができるようになります。キャプチャの順序は開きカッコの出現順です。たとえば、パターン"(a*(.)%w(%s*))"において、最初のキャプチャはa*(.)%w(%s*)に相当する部分文字列であり、2番目のキャプチャは.に、3番目のキャプチャは%s*に相当する部分文字列となります。

Luaパターンの特殊なケースとして、空っぽのキャプチャ()は、その場所の文字列の中での位置をキャプチャします。たとえば、パターン"()aa()"を文字列"flaaap"に適用した場合、3と5がキャプチャされます。この空っぽのキャプチャは正規表現では使えません。

正規表現糖衣構文

正規表現は、Luaの正式な型ではなく、ユーザーデータ型の一種です。正規表現オブジェクト(正規表現を実現するためのデータ等が格納されたユーザーデータ型の値)は、string.regexp関数の戻り値として与えられますが、以下のような記述方法で簡潔に表現することも可能です。

正規表現と正規表現糖衣構文は_RT_LUA_VERSION"1.03"以降のファームウェアで扱うことができます。
/abc[def]ghi/i <==> string.regexp([=[abc[def]ghi]=], "i")
    

関数で文字列を一つだけ引数にとる場合には関数名の後ろのカッコが省略できますが、引数が正規表現の場合にはカッコは省略できません。正規表現糖衣構文の先頭のスラッシュ(/)が割り算記号であると解釈されるためです。

str = "hello world"
a, b = str:split(/\s/)  --- 成功
a, b = str:split "%s"   --- 成功
a, b = str:split /\s/   --- エラー、/ は割り算記号として扱われる
    

正規表現糖衣構文は、数値や文字列のようにデータを直接プログラム中に記述しているわけではなく、あくまでstring.regexp関数の呼び出しを簡潔に記述しているだけです。正規表現文字列等にエラーがある場合でも、実際にその文を実行してみるまではエラーは分かりません。

テーブル操作

table.concat(tbl, sep, i, j)

テーブルを配列として扱う関数です。

テーブルtblの各要素の値を、tbl[i]からtbl[j]まで、sepを区切り文字として連結した文字列を返します。tbl[i]からtbl[j]までの値は文字列型か数値型でなければならず、数値型の場合はtonumber関数を適用した文字列を連結します。

sepを省略した場合は空文字列となります。iを省略した場合は1、jを省略した場合はtblの長さとなります。もし、jの方がiより大きい場合は、戻り値は空文字列となります。

t = { "hello", "world", "from", "Lua" }
s = table.concat(t, ";") -- s = "hello;world;from;Lua"
    

table.insert(tbl, pos, value)

テーブルを配列として扱う関数です。

valueを持つ要素を、テーブルtblpos番目に挿入します。pos番目以降の要素は一つずつ後ろにずらされます。posを省略したときには、要素はテーブルの最後に追加されます。

table.insertは戻り値を何も返しません。。

t = { "A", "B" }
table.insert(t, 2, "C") -- t = { "A", "C", "B" }
table.insert(t, "D")    -- t = { "A", "C", "B", "D" }
    

table.maxn(tbl)

テーブルtblの持つ要素のキーのうち、正の数値(FIXNUM)であるものの中で最大のものを返します。tblが正の数値(FIXNUM)のキーの要素を持たない場合は0を返します。

この関数は結果を求めるためにテーブルを線形にすべて巡回します。そのため、大きなテーブルに対しては実行時間が長くかかります。テーブルが配列である場合は、長さ演算子#を用いたほうがよいでしょう。

t = { [1] = "A", [100] = "B", x = "C", [3] = "D" }
x = table.maxn(t) -- x = 100
    

table.remove(tbl, pos)

テーブルを配列として扱う関数です。

テーブルtblからpos番目の要素を削除し、その後ろの要素を一つずつ前に詰めます。posを省略したときには、最後の要素を削除します。

table.removeは戻り値を何も返しません。

t = { "A", "B", "C", "D" }
table.remove(t, 2) -- t = { "A", "C", "D" }
table.remove(t) -- t = { "A", "C" }

table.sort(table, comp)

テーブルを配列として扱う関数です。

テーブルtblをソートします。ソートの対象となるのは、tbl[1]からtbl[n](ただし、n = #tbl)です。compは、ソートの際の大小比較に用いる関数であり、tblの要素の値を2つ引数にとり、最初の引数が2番目の引数より小さかったらtrue、そうでなければfalseを返さなければなりません。compが省略された場合は、通常の比較演算子である<に相当する関数が使用されます。

ソートのアルゴリズムは安定ではありません。すなわち、値が等しいとみなせる要素が複数あったときに、ソートの前後でそれらの順序は変わっているかもしれません。

table.sortは戻り値を何も返しません。

t = { 2, 4, 3, 1 }
table.sort(t)     -- t = { 1, 2, 3, 4 }
    

数学関数

_RT_LUA_VERSION"1.01"以降のファームウェアで使用可能です。

math.abs(x)

xの絶対値を返します。

x = -1
y = math.abs(x)     -- y = 1
    

math.fmod(x, y)

除算の丸め方向を、除算演算子(/)とは異なり、0方向へ丸めるとした場合の、xyで除したときの剰余を返します。

x = 5
y = -2
z1 = 5 % -2           -- z1 = -1
z2 = math.fmod(x, y)  -- z2 = 1
    

math.max(v, v...)

引数のうち、最大の値を返します。

x = 5
y = -2
z = 3
w = 1
r = math.max(x, y, z, w)    -- r = 5
    

math.min(v, v...)

引数のうち、最小の値を返します。

x = 5
y = -2
z = 3
w = 1
r = math.min(x, y, z, w)    -- r = -2
    

math.random(m, n)

m以上、n以下の範囲の擬似乱数を返します。擬似乱数の種はmath.randomseed関数で指定します。

mを省略した場合は1とみなします。nは省略できません。

math.randomseed(os.time())
r = math.random(100)        -- r = 1〜100
r = math.random(1000, 2000) -- r = 1000〜2000
    

math.randomseed(s)

math.random関数が生成する擬似乱数の種を指定します。

擬似乱数の種が同一の場合、math.random関数はまったく同じ乱数列を返します。乱数として意味を持たせるためには、以下の例のようにos.time関数を使うなどして、スクリプトの起動ごとに異なる種が与えられるようにしてください。

math.randomseed(os.time())
r = math.random(100)        -- r = 1〜100
r = math.random(1000, 2000) -- r = 1000〜2000
    

入出力

入出力ライブラリには2つの種類があります。一つは、ファイルハンドルを明示せず、デフォルトの入出力ファイルに対して操作を行うものであり、もう一つはファイルハンドルを明示して操作を行うものです。

ファイルハンドルとは、io.inputio.outputio.openの3つの関数の戻り値であり、ライブラリがファイルを操作する場合に必要な情報をセットしたuserdata型のデータです。ファイルハンドルを明示しない操作では、対象となるファイルはio.inputおよびio.outputで指定され、テーブルioの要素である関数によって入出力動作が行われます。一方、ファイルハンドルを明示する操作は、io.openの戻り値であるファイルハンドルに対するメソッドとして定義されています。

標準のLua言語では、あらかじめ定義されたファイルハンドルとしてio.stdinio.stdoutio.stderrの3つが利用できますが、ヤマハルーターではこれらは利用できません。また、io.inputio.outputも、これらを初期値として持つことはできず、初期値は何もファイルに結び付けられていない状態となります。

file:close()

ファイルハンドルfileに対するメソッドであり、fileをクローズします。

fileのクローズに成功した場合はtrueを返します。そうでない場合は、nil、エラーメッセージ(文字列)、エラーコード(数値)の3つを返します。

f = io.open("FILE.txt")
f:read(), f:write(),…
f:close()
    

io.close(file)

ファイルハンドルfileをクローズします。fileを省略した場合は、io.outputで指定したデフォルト出力ファイルをクローズします。

ファイルのクローズに成功した場合はtrueを返します。そうでない場合は、nil、エラーメッセージ(文字列)、エラーコード(数値)の3つを返します。

io.output("FILE.txt")
io.write(),…
io.close()
    

file:flush()

ファイルハンドルfileに対するメソッドであり、fileに対して行われた書込み操作のうち、まだ実際にはメディア等に書き込まれておらず、OS内のバッファにとどまっているデータを、メディア等に書き込みます。

書き込むべきデータが残っていなかったか、データの書き込みに成功した場合はtrueを返します。そうでない場合は、nil、エラーメッセージ(文字列)、エラーコード(数値)の3つを返します。

f = io.open("FILE.txt", "w")
f:write(),…
f:flush()
    

io.flush()

io.outputで指定されたデフォルト出力ファイルに対して行われた書込み操作のうち、まだ実際にはメディア等に書き込まれておらず、OS内のバッファにとどまっているデータを、メディア等に書き込みます。

書き込むべきデータが残っていなかったか、データの書き込みに成功した場合はtrueを返します。そうでない場合は、nil、エラーメッセージ(文字列)、エラーコード(数値)の3つを返します。

io.output("FILE.txt")
io.write(),…
io.flush()
    

io.input(file)

fileが文字列の場合は、それをファイル名とみなしてオープンし、標準入力ファイルとします。fileがファイルハンドルの場合は、それをそのまま標準入力ファイルとします。いずれの場合も、新しく利用できる標準入力ファイルのファイルハンドルを返します。fileが省略された場合は、現在利用できる標準入力ファイルのファイルハンドルを返します。

指定したファイルがオープンできないなどの場合はエラーとなります。

io.input("FILE.txt")
io.read()…
    

file:lines()

ファイルハンドルfileに対するメソッドであり、fileから一行ずつ読み出してくるイテレータ関数を返します。ファイルの終端に達したときには、イテレータ関数はnilを返しますがファイルはクローズしません。

一般for文と一緒に使うことで、ファイルを一行ずつ処理するコードを以下のように書くことができます。

f = io.open("FILE.txt")
for line in f:lines() do
  -- "FILE.txt"を一行ずつ処理するコード
end
    

io.lines(filename)

filenameを指定した場合は、そのファイルをオープンしてから、ファイルの内容を一行ずつ返すイテレータ関数を返します。ファイルの終端に達したときには、イテレータ関数はnilを返し、ファイルをクローズします。

filenameを省略した場合は、io.inputで指定するデフォルト入力ファイルに対して、一行ずつ内容を返すイテレータ関数を返します。ファイルの終端に達したときには、イテレータ関数はnilを返しますがファイルはクローズしません。

一般for文と一緒に使うことで、ファイルを一行ずつ処理するコードを以下のように書くことができます。

for line in io.lines("FILE.txt") do
  -- "FILE.txt"を一行ずつ処理するコード
end
    

io.open(filename, mode)

ファイルfilenamemodeに指定されたモードでオープンし、ファイルハンドルを返します。ファイルのオープンに失敗した場合は、nil、エラーメッセージ(文字列)、エラーコード(数値)の3つを返します。

modeは文字列であり、以下のいずれかでなければなりません。modeを省略した場合は、"r"であると解釈されます。

文字列 説明
"r" テキストモードで読み出し
"w" テキストモードで書き込み
"a" テキストモードで追記 (外部メモリ上のファイルのみ)
"rb" バイナリモードで読み出し
"wb" バイナリモードで書き込み
"ab" バイナリモードで追記 (外部メモリ上のファイルのみ)

テキストモードでは、以下の通り改行コードの変換処理が行われます。

改行コードを変換しない場合はバイナリモードでオープンします。

--[[
ファイルをコピーする関数
source, destination: ファイル名を表す文字列
]]
function file_copy(source, destination)
  local fhs, fhd, buf, estr, ecode
  fhs, estr, ecode = io.open(source, "r")
  if fhs == nil then
    return nil, estr, ecode
  end
  fhd, estr, ecode = io.open(destination, "w")
  if fhd == nil then
    fhs:close()
    return nil, estr, ecode
  end
  repeat
    buf = fhs:read(1000)
    if buf then
      fhd:write(buf)
    end
  until buf == nil
  fhd:close()
  fhs:close()
  return true
end
    

io.output(file)

fileが文字列の場合は、それをファイル名とみなしてオープンし、標準出力ファイルとします。fileがファイルハンドルの場合は、それをそのまま標準出力ファイルとします。いずれの場合も、新しく利用できる標準出力ファイルのファイルハンドルを返します。fileが省略された場合は、現在利用できる標準出力ファイルのファイルハンドルを返します。

指定したファイルがオープンできない場合はエラーとなります。

io.output("FILE.txt")
io.write("Hello, world")  -- "FILE.txt"に、"Hello, world"と書き込む
    

file:read(format, ...)

ファイルハンドルfileに対するメソッドであり、fileからformatに沿った形でデータを読み出して返します。データが読み出せた場合は、それを文字列として返しますが、データが読み出せない場合はnilを返します。戻り値の個数は、引数の個数と同じです。

formatは以下のいずれかである必要があります。formatを省略した場合は、"*l"が一つだけ指定されたものとみなされます。

io.read(format, ...)

io.inputで指定する標準入力ファイルに対して読み出しを行います。formatの意味や戻り値などはすべてfile:readと同じです。

io.type(file)

fileがファイルハンドルであるかどうかを調べます。

fileがオープンされているファイルに対するファイルハンドルである場合は、文字列"file"を返します。クローズされているファイルに対するファイルハンドルである場合は、文字列"closed file"を返します。fileがファイルハンドルでない場合には、nilを返します。

file:write(value, ...)

ファイルハンドルfileに対するメソッドであり、指定したデータをfileに文字列として書き出します。

io.write(value, ...)

指定したデータをio.outputで指定した標準出力ファイルに文字列として書き出します。

ビット演算

_RT_LUA_VERSION"1.01"以降のファームウェアで使用可能です。

bit.band(v, v...)

与えられた引数32ビット符号無し整数とみなし、そのビットごとの論理積をとった値を返します。

x = 0x5a
y = 0xaf
z = bit.band(x, y) -- z = 0x0a
    

bit.btest(v, v...)

与えられた引数32ビット符号無し整数とみなし、そのビットごとの論理積をとった値が0であればfalseを、そうでなければtrueを返します。

x = 0x01
y = 0x02
z = bit.btest(x, y)   -- z = false

x = 0x01
y = 0x03
z = bit.btest(x, y)   -- z = true
    

bit.bor(v, v...)

与えられた引数を32ビット符号無し整数とみなし、そのビットごとの論理和をとった値を返します。

x = 0x5a
y = 0xa5
z = bit.bor(x, y)  -- z = 0xff
    

bit.bxor(v, v...)

与えられた引数を32ビット符号無し整数とみなし、そのビットごとの排他的論理和をとった値を返します。

x = 0x5a
y = 0xff
z = bit.bxor(x, y)  -- z = 0xa5
    

bit.bnot(v)

与えられた引数を32ビット符号無し整数とみなし、そのビットごとの論理否定をとった値を返します。

x = 0x5a
z = bit.bnot(x, y)  -- z = 0xffffffa5
    

bit.bshift(v, s)

vを32ビット符号無し整数とみなし、sだけシフトした値を返します。sの符号が正の場合は左シフト、負の場合は右シフトとなります。

sの絶対値が32以上の場合は、戻り値は0となります。

x = 0x5a
y = 4
z = bit.bshift(x, y)  -- z = 0x05a0

x = 0x05a0
y = -8
z = bit.bshift(x, y)  -- z = 0x0005
    

bit.brotate(v, s)

vを32ビット符号無し整数とみなし、sだけ回転した値を返します。sの符号が正の場合は左方向への回転、負の場合は右方向への回転となります。

x = 0x12345678
y = 4
z = bit.brotate(x, y)  -- z = 0x23456781

x = 0x12345678
y = -8
z = bit.brotate(x, y)  -- z = 0x78123456
    

ヤマハルーターAPI

基本ライブラリ

rt.command(cmd, log)

文字列cmdをルーターのコマンドとして実行します。cmdの長さは4095バイト以内でないといけません。またcmdにはパイプ ("|") やリダイレクト記号 (">", ">>") を含むことができます。cmdに指定できるコマンドは1つのみで、複数のコマンドを指定することはできません。

logoffを指定すると、実行したコマンドと実行の成否 (true/false) が、SYSLOGに出力されなくなります。logを省略、またはonを指定した場合、従来と同様に実行したコマンドと実行の成否 (true/false) が、DEBUGタイプでSYSLOGに出力されます。
log_RT_LUA_VERSION"1.07"以上のファームウェアで指定可能です。

戻り値には、コマンドの実行結果が返ります。最初の戻り値として、コマンドが正しく実行できればtrueが、何らかのエラーが発生していればfalseが返ります。2つ目の戻り値には、コマンドの出力、あるいはエラーメッセージが文字列として返ります。何も返す文字列がない場合にはnilが返ります。2つ目の戻り値の文字列の文字コードは、console characterコマンドの設定に従います。

ルーターのコマンド出力では、改行は"\r\n"の2文字で表されます。

rt.commandでは、すべてのコマンドを管理ユーザー権限で実行します。

以下のコマンドは、rt.commandからは実行できません。

以下のコマンドは、通常とは動作が異なります。

rtn, str = rt.command("show status lan2")
-- rtn = true
-- str = [[
LAN2
説明:
IPアドレス:		192.168.2.1/24
イーサネットアドレス:	00:a0:de:12:34:56
動作モード設定:		Auto Negotiation (Link Down)
最大パケット長(MTU):	1500 オクテット
…
]]
rtn, str = rt.command("show status tunnel 9999")
-- rtn = false
-- str = "エラー: パラメータが範囲を越えています\r\n"
    

rt.mail(param)

テーブルparamで指定したパラメータに従ってメールを送信します。

rt.mailが呼び出されると、1秒待機してからメールを送信します。メール送信が完了すると、trueを返します。サーバーと通信できない場合などにはfalseを返します。

paramに指定できるパラメータは以下のとおりです。

キー文字列 設定値 必須(M)
オプション(O) 省略時の値
smtp_address SMTPサーバーアドレスまたはホスト名を示す文字列 (最大64文字) 文字列型 M
smtp_port SMTPサーバーのポート番号 (1 .. 65535) 数値型 O smtps=false のとき 25、smtps=true のとき 465
smtp_auth_name SMTP認証用ユーザー名を示す文字列 (最大64文字) 文字列型 O なし
smtp_auth_password SMTP認証用パスワードを示す文字列 (最大64文字) 文字列型 O なし
smtp_auth_protocol SMTP-AUTH認証プロトコルを示す文字列で、以下のいずれか
"cram-md5""digest-md5""plain"
文字列型 O 示した順番に認証交渉を行う
pop_before_smtp POP before SMTP動作を行う場合にtrueを指定
smtps と同時に指定することはできない
論理型 O false
pop_port POPサーバーのポート番号 (1 .. 65535) 数値型 O 110
timeout 送受信処理のタイムアウト秒数(1 .. 600 数値型 O 60
from 送信元メールアドレスを示す文字列 文字列型 M
to 宛先メールアドレスを示す文字列
複数指定する場合はコンマ(,)で区切り、空白を入れてはいけない
文字列型 M
subject 題名を示す文字列 (最大64文字) 文字列型 O ""
date メールヘッダに表示する時刻を示す文字列で、RFC822に示されるフォーマットで時刻を指定する 文字列型 O 送信時のルーターの時刻
mime_version メールヘッダに表示するMIME-Versionを示す文字列 文字列型 O "1.0"
content_type メールヘッダに表示するContent-Typeを示す文字列
type/subjectには"text/plain"、パラメータには"charset=us-ascii"および"charset=iso-2022-jp"が指定可能
文字列型 O "text/plain; charset=iso-2022-jp"
text 本文を示す文字列 (RTX3500/RTX5000:最大8000KB, RTX3510/RTX1300/RTX1220/RTX1210:最大3MB, RTX1200:最大1250KB, RTX810/RTX830/NVR500/FWX120:最大640KB, SRT100:最大500KB)
改行文字とタブ文字以外の制御文字を含ませることはできない
文字列型 O ""
preface_of_text 本文の先頭にルーターの情報を挿入しない場合falseを指定
_RT_LUA_VERSION"1.05"以上のファームウェアで指定可能
論理型 O true
smtps SMTPS を用いてメールを送信する場合trueを指定
pop_before_smtp と同時に指定することはできない
_RT_LUA_VERSION"1.08"以上のファームウェアで指定可能
論理型 O false
pop_before_smtpがtrueの場合に必須となるパラメータ
pop_address POPサーバーアドレスまたはホスト名を示す文字列 (最大64文字) 文字列型 M
(pop_before_smtpがtrueのとき)
pop_protocol 受信プロトコルを示す以下の文字列
"pop3", "apop"
文字列型
pop_auth_name POP 認証用ユーザー名を示す文字列 (最大64文字) 文字列型
pop_auth_password POP 認証用パスワードを示す文字列 (最大64文字) 文字列型

cmd = "show techinfo"
mail_table = {
  smtp_address = "mx.example.jp",
  from = "foo@example.jp",
  to = "bar@example.jp",
  subject = cmd
}

rtn, str = rt.command(cmd)
if rtn and str then
  mail_table.text = cmd .. "の実行結果\r\n\r\n" .. str
  rt.mail(mail_table)
end

rt.sleep(seconds)

rt.sleepを呼び出すと、seconds秒後に関数から返ってきます。secondsは1から864000の間の数値でなくてはなりません。

関数の戻り値は0です。rt.sleepはLuaスクリプトの実行を遅延させたい場合に用います。関数の実行中、呼び出し元のLuaタスクはほとんどCPUを消費しません。

while true do
  …
  rt.sleep(600) -- 10分おきに何らかの処理を繰り返す
end
    

rt.syslog(type, text)

textをログとして記録します。また、syslog serverコマンドなどが設定されていれば、SYSLOGとしても出力します。textは231バイト以内でなければなりません。

typeはログの種類で、以下のいずれかでなくてはなりません。

戻り値には、論理型と文字列型の2つが返ります。最初の論理型の戻り値はログ出力の成功、失敗を表し、2番目の戻り値はエラーメッセージとなります。typenotice/debugを指定した場合は、対応するsyslog notice/debugコマンドの設定がoffになっていると ログ出力は失敗し、falseが返ります。typeinfoを指定した場合は、対応するsyslog infoコマンドの設定に関わらず常にログ出力を行いますが、SYSLOGサーバーへの送信はsyslog infoコマンドの設定がonになっている場合にのみ行われます。

rt.syslog("info", "[Lua] This is a LOG")
    

rt.syslogwatch(pattern, n, seconds)

ルーターのログに、パターンpatternに合致する行がn回新しく記録されるか、seconds秒が経過するとこの関数は終了し、処理が戻ってきます。ログのタイムスタンプ部分はpatternの比較対象とはなりません。

nは1〜1000の数値で、省略したときは1とみなします。secondsは1〜864000の数値で、省略時はpatternに合致するログが現れるまで永遠に待ちます。

戻り値としては、patternに合致した回数、および、合致したログ(タイムスタンプつき)を格納した配列が返されます。secondsの満了により返ってくる場合には、それまでに合致した回数とログが返されます。一度も合致するログがなかった場合には、回数は0となり、2つ目の戻り値はnilとなります。

一行のログにpatternが複数回合致するようなケースでも、合致回数は1と数えます。

rt.syslogwatchを呼び出している間は、ログの記録がなければ呼び出し元のLuaタスクはほとんどCPUを消費しません。

pattern = "IP Tunnel%[(%d+)%] Down"
while true do
  rtn, array = rt.syslogwatch(pattern, 1, 600)
  if rtn > 0 then
    io.output("FILE.txt")
    io.write(string.format("トンネルダウン: %s\n", string.match(array[1], pattern)))
    io.close()
  end
end
    

ハードウェアライブラリ

rt.hw.open(resource, type)

resourceで指定したハードウェアをオープンしてLuaスクリプトで制御可能な状態にし、そのディスクリプタを返します。
resourceとして指定できるのは下記のいずれかです。

[_RT_LUA_VERSION"1.02"以上で指定可能] [_RT_LUA_VERSION"1.04"以上で指定可能]

ハードウェアのオープンに成功した場合、1つ目の戻り値としてディスクリプタが返り、2つ目の戻り値はnilになります。ハードウェアのオープンに失敗した場合、1つ目の戻り値はnilになり、2つ目の戻り値にエラー内容を示す文字列が返ります。

typeはUSBキーボードのタイプを示す文字列で、typeはUSBキーボード"keyboard1"を制御する場合にのみ 指定可能です。他のハードウェアのオープン時に指定した場合、当関数はエラー終了します。
typeとして指定できるのは下記のいずれかです。

typeを省略した場合には、"jp"が指定されたものとしてキーボードを制御します。

当関数でオープンしたハードウェアは、呼び出し元のLuaタスクが占有するため、hwd:closeでクローズするまでは他のLuaタスクから制御することができません。 なお、温度計 "thermometer1"と CPU "cpu1"以外のハードウェアに関しては、Luaタスクが占有しているときは他のルーターの機能からも制御することができなくなるため、ハードウェア本来の動作はしなくなるため注意が必要です。

-- 1分毎にCPU負荷率を調べ、80%を超えていたら、ブザーを鳴らす。

threshold = 80
sleep_sec = 60

while (true) do
	cpu, err = rt.hw.open("cpu1")
	if (cpu) then
		load = cpu:read()
		cpu:close()
	end

	if (load.load_1m > threshold) then
		bz, str = rt.hw.open("buzzer1")
		if (bz) then
			bz:tone("B3")
		end
	else
		if (bz) then
			bz:off()
			bz:close()
		end
	end

	rt.sleep(sleep_sec)
end
    

以下は_RT_LUA_VERSION"1.02"以降のファームウェアで使用可能です。

hwd:close()

ディスクリプタhwdに対するメソッドであり、hwdをクローズしてハードウェアの制御を終了します。

bz, str = rt.hw.open("buzzer1")
bz:tone("B2")
rt.sleep(10)
bz:off()
bz:close()
    

hwd:tone(tune)

ブザーのディスクリプタhwdに対するメソッドであり、tuneで指定した音程のブザー音を鳴らします。

tuneは音程を表す文字列で、"C1" のように、C、D、E、F、G、A、Bのうちのアルファベットと 1桁の数字との組合せで指定します。 "C1"の"C"は音階を表し、Cから順に ド、レ、ミ、ファ、ソ、ラ、シ に対応します。 また、"1"は音の高さを表し、数値が1つ大きくなるとブザー音は1オクターブ高くります。 出力できる音程は表のとおりです。

機種 出力できる音程
NVR500、NVR510、NVR700W、FWX120、RTX810、RTX830、RTX1200、RTX1210、RTX1220、RTX1300、RTX3500、RTX3510、RTX5000 B2、E3、B3、B4
SRT100 B2、B3
bz, str = rt.hw.open("buzzer1")
bz:tone("B2")…
    

hwd:on()

LEDのディスクリプタhwdに対するメソッドであり、LEDを点灯させます。

led, str = rt.hw.open("status-led1")
led:on()…
    

LEDのディスクリプタhwdに対するメソッドであり、LEDを点滅させます。

interval_on/interval_offは、LEDの点滅における点灯/消灯の時間(ミリ秒)であり、それぞれ100ミリ秒単位で100から3000の範囲で指定できます。100で割り切れない値が指定された場合10の位以下は切り捨てられます。

led, str = rt.hw.open("status-led1")
led:blink(500, 500)…
    

hwd:off()

ディスクリプタhwdに対するメソッドであり、hwdがブザーのディスクリプタの場合には鳴っているブザーを停止します。hwdがLEDのディスクリプタの場合には点灯もしくは点滅しているLEDを消灯します。

led = rt.hw.open("status-led1")
led:on()
led:off()…
    

hwd:read(n)

ディスクリプタhwdに対するメソッドであり、hwdが温度計のディスクリプタの場合にはルーター筐体内の温度計の値を読み取り、戻り値には数値型で温度が返ります。hwdがCPUのディスクリプタの場合にはCPU負荷率を取得し、戻り値には、各測定間隔のCPU負荷率を格納したテーブルが返ります。 テーブルの内容は表のとおりです。

フィールド名 データ型 CPU負荷率の測定間隔
load_5s 数値型 5秒間
load_1m 数値型 1分間
load_5m 数値型 5分間

_RT_LUA_VERSION"1.04"以降のファームウェアでは、hwdが USBキーボードの場合、キーボードからの出力をnで指定した文字数だけ読み取ります。 戻り値には、キーボードから読み取った文字が返ります。

なお、hwdが温度計、CPUのディスクリプタの場合には、nを指定することはできません。

[CPU負荷率を読み取る例]
cpu, err = rt.hw.open("cpu1")
if cpu then
  val_t = cpu:read()
  cpu:close()
  print("5分間のCPU負荷率 : " .. tostring(val_t.load_5m) .. "%")
else
  print(err)
end



[キーボードから文字を読み取る例]
kbd, err = rt.hw.open("keyboard1", "jp")
if kbd then
  data = kbd:read(5)
  kbd:close()
  print(data)
else
  print(err)
end
    

以下は_RT_LUA_VERSION"1.04"以降のファームウェアで使用可能です。

hwd:getc(NOWAIT)

USBキーボードのディスクリプタhwdに対するメソッドであり、キーボードからの出力を1文字読み取ります。

NOWAITfalseを指定した場合には、ノーウェイトでキー入力を読み取ることができます。

kbd, str = rt.hw.open("keyboard1")
if kbd then
  str = ""

  data = kbd:getc()
  while data ~= '\n' do
    if data then
	    str = str .. data
      data = kbd:getc()
    end
  end

  kbd:close()
  print(str)
else
  print(str)
end
    

hwd:getchar()

USBキーボードのディスクリプタhwdに対するメソッドであり、キーボードからの出力を1文字読み取ります。

NOWAITを指定することができない点以外はhwd:getc関数と同様に使用することができます。

hwd:gets()

USBキーボードのディスクリプタhwdに対するメソッドであり、キーボードからの出力を改行までの1行を読み取ります。

kbd, str = rt.hw.open("keyboard1")
if kbd then
  data = kbd:gets()
  if data then
    print(data)
  end
  kbd:close()
end
    

HTTPライブラリ

_RT_LUA_VERSION"1.02"以降のファームウェアで使用可能です。

rt.httprequest(param)

テーブルparamで指定したパラメータに従ってHTTPによるデータの送受信を行います。

rt.httprequestが呼び出されると、パラメータの内容に沿ったHTTP RequestがHTTPサーバーに対して送信され、それに対するResponseが受信されると関数から処理が戻ります。関数からの戻り値として、HTTP通信の実行結果とサーバーから受信したデータを格納したテーブルが返されます。

paramに指定できるパラメータは以下のとおりです。

キー文字列 設定値 必須(M)
オプション(O) 省略時の値
url リクエストの送信先URL
"http(s)://サーバーのIPアドレスあるいはホスト名/パス名"という形式で入力する。
サーバーのポート番号が 80 (http)、または 443 (https) 以外の場合は、"http(s)://サーバーの IP アドレスあるいはホスト名:ポート番号/パス名" という形式で、URL の中に指定する。
指定可能な最大文字数は以下の通り。
機種およびファームウェア最大文字数
RTX5000 Rev.14.00.34以降 2048
RTX3510 Rev.23.01.02以降
RTX3500 Rev.14.00.34以降
RTX1300 Rev.23.00.05以降
RTX1220 Rev.15.04.05以降
RTX830 Rev.15.02.29以降
NVR700W Rev.15.00.24以降
NVR510 Rev.15.01.25以降
上記以外255
文字列型 M
method リクエストに使用するHTTPメソッドを示す文字列で、以下のいずれか
"GET""HEAD""POST"
文字列型 M
proxy リクエストに使用するHTTP proxyサーバーを示す文字列 (最大128文字) 文字列型 O なし
proxy_port リクエストに使用するHTTP proxyサーバーのポート番号 (1 .. 65535)
proxyフィールドにHTTP proxyサーバーを指定し、かつ本フィールドを省略した場合には、本フィールドに80が指定されたものとして動作する。
数値型 O なし
auth_type 認証方式を示す文字列で、以下のいずれか
"none"(認証なし)、"basic"(Basic認証)、"bearer"(Bearer認証)
"bearer"_RT_LUA_VERSION"1.08"以上のファームウェアで指定可能
文字列型 O "none"
auth_name 認証用ユーザー名を示す文字列 (最大64文字) 文字列型 auth_type="basic"のとき、必須
auth_pass 認証用パスワードを示す文字列 (最大64文字) 文字列型
auth_token 認証用トークンを示す文字列 (最大256文字)
_RT_LUA_VERSION"1.08"以上のファームウェアで指定可能
文字列型 auth_type="bearer"のとき、必須
timeout リクエスト処理のタイムアウト秒数 (1 .. 180 数値型 O 30
save_file 受信したデータをファイルに保存する場合の保存先のファイル名 (最大64文字)
"config0" .. "config4"というファイル名を指定すると、ルーターの設定ファイルへの保存となる。(NVR500では"config0"のみ)
methodに"HEAD"を指定した場合は無視される。
文字列型 O なし
post_text POSTメソッドで送信するデータ本体を表す文字列 (RTX3500/RTX5000:最大8000KB, RTX3510/RTX1300/RTX1220/RTX1210:最大3MB, RTX1200:最大1250KB, RTX810/RTX830/NVR500/NVR510/NVR700W/FWX120:最大640KB, SRT100:最大500KB)
methodに"POST"以外を指定した場合は無視される。また、post_fileと同時に指定することはできない。
文字列型 method="POST"のとき、いずれか一方のみを必ず指定する必要がある
post_file POSTメソッドで送信するファイル名 (最大64文字)
methodに"POST"以外を指定した場合は無視される。また、post_textと同時に指定することはできない。
文字列型
content_type POSTメソッドで送信するデータの形式を示す文字列 (最大128文字)
methodに"POST"以外を指定した場合は無視される。
文字列型 method="POST"のとき、必須

また、戻り値は以下のようなテーブルとなる。

キー文字列 説明
rtn1 HTTPリクエストの送信結果を表し、サーバーからのレスポンスデータの受信に成功するとtrueが、失敗するとfalseが格納される。 論理型
rtn2 save_filepost_fileで指定したファイルに対する入出力の結果を表し、ファイルの入出力に成功するとtrueが、失敗するとfalseが格納される。ファイルの入出力が行われない場合には、このフィールドは存在しない。 論理型
err HTTPの送受信やファイル入出力でエラーが発生した場合にエラーメッセージが格納される。エラーが発生しなかった場合には、このフィールドは存在しない。 文字列型
code サーバーからのレスポンスのHTTPステータスコードが格納される。 数値型
header サーバーからのレスポンスのHTTPヘッダーが格納される。 文字列型
body サーバーからのレスポンスデータの本体が格納される。データサイズの上限(RTX3500/RTX5000:2MB、RTX3510/RTX1300/RTX1220/RTX1210/RTX1200/RTX810/RTX830/NVR500/NVR510/NVR700W/FWX120:1MB、SRT100:250KB)を超えた場合にはnilが格納される。 文字列型またはnil型

ソケット通信ライブラリ

_RT_LUA_VERSION"1.06"以降のファームウェアで使用可能です。

ソケット通信ライブラリは、LuaSocketのC言語で記述されたライブラリ関数を移植したものです。LuaSocketのバージョンは 2.0.2 です。

LuaSocketはC言語で書かれたライブラリ関数と、Lua言語で書かれたライブラリ関数に分かれています。C言語で書かれたライブラリ関数が、ソケットシステムコールを呼び出すような低レベルの関数を用意しているのに対して、Lua言語で書かれたライブラリ関数は、HTTPやFTP、SMTP等のアプリケーションを利用するための関数を用意しています。
ルーターにはLuaSocketのC言語で書かれたライブラリ関数をAPIとして移植しているため、Lua言語のライブラリ関数についてもLuaSocketのホームページで公開されているスクリプトをそのまま使用することができません。以下にあるヤマハルーター用LuaSocketモジュールファイルを使用してください。 また、Lua言語で書かれたライブラリ関数についてはLuaSocketのリファレンスをご覧ください。

ヤマハルーター用LuaSocketモジュールファイル

本ライブラリでは、ソケットオブジェクトを生成し、オブジェクト単位での通信を行います。オブジェクトはプロトコル毎に性質が異なり、特定の関数によって状態を遷移させます。

注意事項

rt.socket.tcp()

TCPのマスターオブジェクトを生成します。

生成したマスターオブジェクトは、この後tcp:listenを呼び出してサーバーオブジェクトに遷移したり、tcp:connectを呼び出してクライアントオブジェクトに遷移したりします。

オブジェクトの生成に成功した場合、生成したオブジェクト(ユーザーデータ型)を返します。オブジェクトの生成に失敗した場合は、nil、エラーメッセージの2つを返します。

-- TCPオブジェクトを生成し、コネクションを待ち受ける
tcp = rt.socket.tcp()
tcp:setoption("reuseaddr", true)
res, err = tcp:bind("192.168.100.1", 11111)
if not res and err then
  print(err)
  os.exit(1)
end
res, err = tcp:listen()
if not res and err then
  print(err)
  os.exit(1)
end

while 1 do
  control = assert(tcp:accept())

  raddr, rport = control:getpeername()
  print("remote host address:" .. raddr .. " port:" .. rport)

  -- 受信待ちタイムアウトを30秒に設定
  control:settimeout(30)
  while 1 do
    msg, err, partial = control:receive()

    if (msg) then
      -- 受信データを処理する(例として、ここではコンソールに出力している)
      print(msg)

      -- レスポンスを送信
      sent, err = control:send("response\n")
      if (err) then
        print("send error(" .. err .. ")")
        control:close()
        break
      end
    else
      if (err ~= "closed") then
        print(os.date() .. "receive error(" .. err .. ")")
        if (partial) then
          print("receive partial data(" .. partial .. ")")
        end
      end
      control:close()
      break;
    end
  end
end
    
-- TCPオブジェクトを生成し、リモートホストへ接続、転送を行う

-- リモートホストのIPアドレス、ポート番号
host = "192.168.100.1"
port = 11111

tcp = rt.socket.tcp()

res, err = tcp:connect(host, port)
if not res then
  print("connect error(" .. err .. ")")
  os.exit(1)
end

print("Connected remote host:" ..host.. " port:" .. port)

lhost, lport = tcp:getsockname()
print("Local host:" ..lhost.. " port:" ..lport)

tcp:settimeout(5)
tcp:setoption("tcp-nodelay", true)

-- データを送信する
sent, err = tcp:send("test\n")
if (err) then
  print("send error(" .. err .. ")")
  tcp:close()
  os.exit(1)
end

-- サーバーからのレスポンスを受信
data, err, partial = tcp:receive()
if (err) then
  print("receive error("..err..")")
  if (partial) then
    print("receive partial data("..partial..")")
  end
  tcp:close()
  os.exit(1)
end

-- 受信データを処理する(例として、ここではコンソールに出力している)
print(data)

tcp:close()
    

rt.socket.udp()

UDPのunconnectedオブジェクトを生成します。

オブジェクトの生成に成功した場合、生成したオブジェクト(ユーザーデータ型)を返します。オブジェクトの生成に失敗した場合は、nil、エラーメッセージの2つを返します。

-- UDPオブジェクトを生成し、リモートホストからのデータ送信を待つ
host = "192.168.100.1"
port = 22222

udp = rt.socket.udp()
res, err = udp:setsockname(host, port)
if (err) then
  print("setsockname error(" .. err .. ")")
  udp:close()
  os.exit(1)
end

lhost, lport = udp:getsockname()
print("Bind to host:" ..lhost.. " and port:" ..lport)

while 1 do
  dgram, ip, port = udp:receivefrom()
  if (dgram ~= nil) then
    -- 受信データを処理する
    -- (例として、ここではコンソールに出力し、受信した文字列をそのまま相手に返している)
    print("Received '" .. dgram .. "' from " .. ip .. ":" .. port)
    udp:sendto(dgram, ip, port)
  else
    print(ip)
    udp:close()
    os.exit(0)
  end
end
    
-- UDPオブジェクトを生成し、リモートホストとの通信を行う
udp = rt.socket.udp()
udp:setpeername("192.168.100.1", 22222)

rhost, rport = udp:getpeername()
print("remote host:" .. rhost .. " port:" .. rport)

-- データを送信
res, err = udp:send("test")
if (err) then
  print("send error(" .. err .. ")")
  udp:close()
  os.exit(1)
end

udp:settimeout(10) -- 受信タイムアウトを10秒に設定

-- 相手からのレスポンスを受信
dgram, err = udp:receive()
if (not dgram) and err then
  print("receive error(" .. err .. ")")
  udp:close()
  os.exit(1)
end
-- 受信データを処理する(例として、ここではコンソールに出力している)
print(dgram)

udp:close()
    

rt.socket.select(recvt, sendt, timeout)

ソケットの状態変化を監視し、読み込みまたは書き出しが可能な状態となったオブジェクトの配列を返します。

recvtには読み込み可能な状態を待つオブジェクト(ユーザーデータ型)の配列を指定し、sendtには書き出し可能な状態を待つオブジェクト(ユーザーデータ型)の配列を指定します。状態変化を待つオブジェクトがない場合には、nilまたは空のテーブルを指定します。
timeoutには状態変化を待つ秒数を指定します。timeoutを省略した場合、または負数を指定した場合は無期限に状態変化を待ちます。

成功した場合、読み込み準備が完了したオブジェクトのテーブル、書き出し準備が完了したオブジェクトのテーブルの2つを返します。このテーブルは整数とオブジェクトの2つがキーとなっており、どのオブジェクトの状態が変化したか一意に分かるようになっています。
エラーが発生した場合、nil、nil、エラーメッセージの3つを返します。

-- 複数のポートでコネクションを待ち受ける
function create(addr, port)
  s = rt.socket.tcp()
  s:setoption("reuseaddr", true)
  res, err = s:bind(addr, port)
  if not res and err then
    print(err)
    os.exit(1)
  end
  res, err = s:listen()
  if not res and err then
    print(err)
    os.exit(1)
  end

  return s
end

server1 = create("192.168.100.1", 11111)
server2 = create("192.168.100.1", 11112)

while 1 do
  rcv, snd, err = rt.socket.select({server1, server2}, nil)

  if rcv[server1] then
    server = server1
  elseif rcv[server2] then
    server = server2
  else
    print("select error:"..err)
    os.exit(1)
  end

  control = assert(server:accept())

  raddr, rport = control:getpeername()
  print("remote host address:" .. raddr .. " port:" .. rport)

  -- 統計情報をクリア
  res = control:setstats(0, 0)

  -- 受信待ちタイムアウトを30秒に設定
  control:settimeout(30)

  while 1 do
    msg, err, partial = control:receive()

    if (msg) then
      -- 受信データを処理する(例として、ここではコンソールに出力している)
      print(msg)

      -- レスポンスを送信
      sent, err = control:send("response\n")
      if (err) then
        print("send error(" .. err .. ")")
        control:shutdown()
        break
      end
    else
      if (err ~= "closed") then
        print(os.date() .. "receive error(" .. err .. ")")
        if (partial) then
          print("receive partial data(" .. partial .. ")")
        end
      end
      control:shutdown()
      break;
    end
  end

  rcv, snd, alive = control:getstats()
  -- 統計情報を表示
  print("receive: " .. rcv .. "bytes, send: " .. snd .. "bytes, alive time: " .. alive .. "sec")

end
    

rt.socket.dns.toip(address)

ホスト名をIPv4アドレスに変換します。

hostnameには、IPv4アドレスまたはホスト名を指定します。

成功した場合、IPv4アドレスとリゾルバから受け取った情報(テーブル型)の2つを返します。リゾルバから受け取った情報は次のテーブルに格納されます。失敗した場合は、nil、エラーメッセージの2つを返します。

キー文字列 設定値
name ホストの正式名称。 文字列型
alias ホストの別名。
(*)ヤマハルーターではホストの別名は取得できませんので、空のテーブルを返します。
文字列型の配列
ip IPv4アドレス。
(*)配列を返しますが、IPv4アドレスは1つだけです。
文字列型の配列
host = "example.com" -- ホスト名を指定
ip, tbl = rt.socket.dns.toip(host)
if ip then
  print(ip) -- 成功した場合、IPアドレスが返される
end
    

rt.socket.dns.tohostname(ip)

IPv4アドレスをホスト名に変換します。

ipには、IPv4アドレスまたはホスト名を指定します。

成功した場合、ホスト名とリゾルバから受け取った情報(テーブル型)の2つを返します。リゾルバから受け取った情報は次のテーブルに格納されます。失敗した場合は、nil、エラーメッセージの2つを返します。

キー文字列 設定値
name ホストの正式名称。 文字列型
alias ホストの別名。
(*)ヤマハルーターではホストの別名は取得できませんので、空のテーブルを返します。
文字列型の配列
ip IPv4アドレス。
(*)配列を返しますが、IPv4アドレスは1つだけです。
文字列型の配列
ip = "10.0.0.1" -- IPアドレスを指定
host, tbl = rt.socket.dns.tohostname(ip)
if host then
  print(host) -- 成功した場合、ホスト名が返される
end
    

rt.socket.dns.gethostname()

機器のホスト名を返します。
ネットボランチDNS や、ip hostコマンドで設定されたルーター自身のホスト名を返します。

成功した場合には機器のホスト名を返します。失敗した場合は、nil、エラーメッセージの2つを返します。

host, err = rt.socket.dns.gethostname(host)
if host then
  print(host) -- 成功した場合、ルーター自身のホスト名が返される
end
    

rt.socket.sleep(seconds)

呼び出し元の Lua タスクをスリープさせます。

rt.socket.sleepを呼び出すと、seconds秒後に関数から返ってきます。

-- 10分置きにUDPパケットを送信する
udp = rt.socket.udp()
udp:setpeername("192.168.100.1", 22222)

while true do
-- データを送信
  res, err = udp:send("notification")
  if (err) then
    print("send error(" .. err .. ")")
    udp:close()
    os.exit(1)
  end

  rt.socket.sleep(600)
end

udp:close()
    

rt.socket.gettime()

ルーターが起動してから経過した秒数を返します。

t1 = rt.socket.gettime()
-- 何かしらの処理をする。
...
t2 = rt.socket.gettime() - t1
print("execute time:" .. t2)
    

rt.socket.newtry(finalizer)

例外エラーを投げる前に処理を行う関数を生成します。

finalizerは、例外エラーを投げる前に保護モードで呼び出される関数です。nilを指定した場合、エラー発生時には何もしません。

例外エラーが発生した際の処理を行う関数を返します。

c = rt.socket.tcp()
sample = rt.socket.protect(function()
    -- エラー発生時にclose()を呼ぶ関数の生成
    local try = rt.socket.newtry(function() c:close() end)
    -- エラー発生時には必ずソケットが閉じられる
    try(c:connect("192.168.100.1", 8888))
    try(c:send("test\r\n"))
    local answer = try(c:receive())
    -- 受信データを処理する
    ...
    return c:close()
end)

ret, err = sample()
if not ret and err then
    print(err)
end
    

rt.socket.protect(func)

関数funcを、保護されたモードで呼び出します。

funcには、newtryやassert、errorを呼んで例外エラーを投げる関数を指定します。

例外エラーを投げない同等の処理を行う関数を返します。その関数は、エラーの場合、nil、エラーメッセージの2つを返します。

こちらの設定例を参照してください。

rt.socket.skip(num, ret1, ret2, ..retN)

指定した数の引数を破棄し、残りの引数を返します。

ret1, ret2.. と列挙した引数のうち、先頭からnum個の引数を破棄し、残りのret[num+1]からretNまでの引数を返します。この関数を使用すると、不要な関数の戻り値を格納するためにダミー変数を用意する必要がなくなります。

num+1 番目以降の引数がある場合、num+1番目以降の引数を全て返します。numと引数の数が同じ場合や、numより引数の数が少ない場合には何も返しません。

-- パターンに合致した位置を表す数値を破棄し、キャプチャされた文字列だけを返す。
r = rt.socket.skip(2, string.find("ABCDE", "B(.)D"))
print(r)

-- コンソールにはキャプチャされた以下の文字が表示される。
-- C
    

rt.socket._VERSION()

ソケット通信ライブラリとして使用しているLuaSocketのバージョンを返します。

tcp:accept()

TCPのオブジェクトtcpのメソッドであり、TCPクライアントからの接続を待ち、コネクションが完了した後クライアントオブジェクトを返します。

tcp:acceptは、サーバーオブジェクトで使用することができます。

成功した場合、クライアントオブジェクト(ユーザーデータ型)を返します。失敗した場合には、nil、エラーメッセージ(文字列)の2つを返します。

こちらの使用例を参照してください。

tcp:bind(address, port)

TCPのオブジェクトtcpのメソッドであり、オブジェクトにIPアドレス、ポート番号を割り当てます。

addressにはオブジェクトに割り当てるIPv4アドレスを指定します。"*"を指定した場合、全てのインタフェースに割り当てます。また、portにはオブジェクトに割り当てるポート番号を指定します。 portに0を指定した場合、システムが自動的に使用するポートを割り当てます。vRXの場合は49152〜65535、vRX以外の機種の場合は1024〜5000の範囲から割り当てます。

DHCPサーバーからIPアドレスが割り当てられるなど動的にIPアドレスが決定される場合には、addressに"*" を指定してください。

tcp:bindは、マスターオブジェクトで使用することができます。

成功した場合、1を返します。失敗した場合には、nil、エラーメッセージの2つを返します。

こちらの使用例を参照してください。

tcp:listen(backlog)

TCPのオブジェクトtcpのメソッドであり、TCPオブジェクトを接続待ち状態にします。

backlogには保留中の接続のキューの最大長を指定します。省略時のデフォルト値は 32 です。

tcp:listenは、マスターオブジェクトで使用することができ、成功した場合にはサーバーオブジェクトへ遷移します。

成功した場合、1を返します。失敗した場合には、nil、エラーメッセージの2つを返します。

こちらの使用例を参照してください。

tcp:close()

TCPのオブジェクトtcpのメソッドであり、TCPオブジェクトを閉じます。

オブジェクトで使用するソケットを閉じ、オブジェクトに割り当てられていたアドレス、ポート番号は他のアプリケーションで使用できるようになります。

tcp:closeは、マスターオブジェクト、サーバーオブジェクト、クライアントオブジェクトで使用することができます。

この関数の戻り値は 1 です。

こちらの使用例を参照してください。

tcp:connect(address, port)

TCPのオブジェクトtcpのメソッドであり、リモートホストへの接続を行います。

addressには接続するリモートホストのIPv4アドレスまたはホスト名を指定し、portにはリモートホストのポート番号を指定します。

接続に成功した場合、関数を呼び出したマスターオブジェクトはクライアントオブジェクトに遷移します。

tcp:connectは、マスターオブジェクトで使用することができます。

成功した場合、1を返します。失敗した場合には、nil、エラーメッセージの2つを返します。

こちらの使用例を参照してください。

tcp:getpeername()

TCPのオブジェクトtcpのメソッドであり、接続したリモートホストの情報を取得します。

tcp.getpeernameは、クライアントオブジェクトで使用することができます。

成功した場合、接続したリモートホストのIPv4アドレス、ポート番号の2つを返します。失敗した場合には、nil、エラーメッセージの2つを返します。

こちらの使用例を参照してください。

tcp:getsockname()

TCPのオブジェクトtcpのメソッドであり、オブジェクトに割り当てられたIPアドレスおよびポート番号を取得します。

tcp:getsocknameは、マスターオブジェクト、サーバーオブジェクト、クライアントオブジェクトで使用することができます。

成功した場合、オブジェクトに割り当てられたIPv4アドレス、ポート番号の2つを返します。失敗した場合には、nil、エラーメッセージの2つを返します。

こちらの使用例を参照してください。

tcp:getstats()

TCPのオブジェクトtcpのメソッドであり、オブジェクトで送受信したバイト数および生存時間(秒)といった統計情報を取得します。

tcp:getstatsは、マスターオブジェクト、サーバーオブジェクト、クライアントオブジェクトで使用することができます。

戻り値は、受信バイト数、送信バイト数、オブジェクトの生存時間の順で返します。

こちらの使用例を参照してください。

tcp:receive(pattern, prefix)

TCPのオブジェクトtcpのメソッドであり、オブジェクトからデータを読み込みます。

patternは以下のいずれかである必要があります。patternを省略した場合は、"*l"が指定されたものとみなされます。

prefixを指定した場合、受信データの前にprefixで指定した文字列が付加されて返されます。prefixを省略した場合には、受信データの前には何も付加されません。

tcp:receiveは、クライアントオブジェクトで使用することができます。

成功した場合には、受信データ(文字列型)を返します。失敗した場合には、nil、エラーメッセージ、エラーが発生するまでに受信したデータ(文字列型)の3つを返します。受信途中でコネクションが閉じられた場合には、エラーメッセージとして"closed"が返されます。

こちらの使用例を参照してください。

tcp:send(data, top, tail)

TCPのオブジェクトtcpのメソッドであり、接続した相手へデータを送信します。

dataには送信するデータを指定します。

topおよびtailを指定した場合、datatopの位置からtailの位置までの間にあるデータを送信します。topを省略した場合はdataの先頭から送信し、tailを省略した場合は、dataの最後までを送信します。
toptailに負数を指定した場合、dataの最後から指定した数を引いた位置が起点となり、その位置がdata内に収まらない場合には、省略時の値が使用されます。また、topよりもtailの位置が前に来る場合には、dataは送信されません。

tcp:sendは、クライアントオブジェクトで使用することができます。

成功した場合には、dataの送信した最後の位置を返します。失敗した場合には、nil、エラーメッセージ、エラーが発生するまでに送信したdataの最後の位置を返します。

こちらの使用例を参照してください。

tcp:setoption(option, value)

TCPのオブジェクトtcpのメソッドであり、オブジェクトに内包するソケットのオプションを設定します。

optionおよびvalueは、それぞれ次の値を取ります。

option value 説明
reuseaddr true ローカルアドレスの再利用を許可する。
false ローカルアドレスの再利用を許可しない。
tcp-nodelay true Nagleアルゴリズムを有効にする。
false Nagleアルゴリズムを無効にする。

tcp:setoptionは、サーバーオブジェクト、クライアントオブジェクトで使用することができます。

成功した場合には 1 を返し、失敗した場合には nil を返します。

こちらの使用例を参照してください。

tcp:setstats(received, sent, age)

TCPのオブジェクトtcpのメソッドであり、オブジェクトの統計情報を指定した値でリセットします。

receivedsentおよびageに指定した値で、それぞれ受信バイト数、送信バイト数、およびオブジェクトの生存時間(秒)をリセットします。

receivedsentageを省略した場合には、現在の受信バイト数、送信バイト数、およびオブジェクトの生存時間がそのまま使用されます。

tcp:setstatsは、マスターオブジェクト、サーバーオブジェクト、クライアントオブジェクトで使用することができます。

成功した場合には 1 を返し、失敗した場合には nil を返します。

こちらの使用例を参照してください。

tcp:settimeout(value, mode)

TCPのオブジェクトtcpのメソッドであり、オブジェクトのタイムアウト時間を設定します。

valueには、タイムアウトまでの秒数を指定します。nil または負数を指定した場合、処理が完了するまで無期限にブロックします。

modeには次の値を指定します。modeを省略した場合、'b' を指定した場合の動作となります。

タイムアウト時間を設定し指定した時間が経過した場合、ブロックしていた関数は処理を中止してエラーを返します。

tcp:settimeoutは、マスターオブジェクト、サーバーオブジェクト、クライアントオブジェクトで使用することができます。

成功した場合、1を返します。失敗した場合には、nil、エラーメッセージの2つを返します。

こちらの使用例を参照してください。

tcp:shutdown(, mode)

TCPのオブジェクトtcpのメソッドであり、送信または受信、およびその両方を遮断します。

modeには次の値を指定します。省略した場合は、both を指定した場合の動作となります。

tcp:shutdownは、クライアントオブジェクトで使用することができます。

戻り値は 1 です。

こちらの使用例を参照してください。

udp:close()

UDPのオブジェクトudpのメソッドであり、ソケットを閉じます。

オブジェクトで使用するソケットを閉じ、オブジェクトに割り当てられていたアドレス、ポート番号は他のアプリケーションで使用できるようになります。

udp:closeは、connectedオブジェクト、unconnectedオブジェクトで使用することができます。

戻り値は 1 です。

こちらの使用例を参照してください。

udp:getpeername()

UDPのオブジェクトudpのメソッドであり、接続したリモートホストのIPアドレスおよびポート番号を取得します。

udp:getpeernameは、connectedオブジェクトで使用することができます。

成功した場合、IPv4アドレスとポート番号を返します。失敗した場合には、nil、エラーメッセージの2つを返します。

こちらの使用例を参照してください。

udp:getsockname()

UDPのオブジェクトudpのメソッドであり、オブジェクトに割り当てられたIPアドレスおよびポート番号を取得します。

UDPでは、setsocknameまたはsendtoのどちらかを最初に呼び出すまで、どのアドレスも割り当てられません。

udp:getsocknameは、connectedオブジェクト、unconnectedオブジェクトで使用することができます。

成功した場合、IPv4アドレスとポート番号を返します。失敗した場合には、nil、エラーメッセージの2つを返します。

こちらの使用例を参照してください。

udp:receive(size)

UDPのオブジェクトudpのメソッドであり、オブジェクトからデータを読み込みます。

sizeには受信するデータグラムの最大サイズを指定します。sizeに指定したデータサイズと、デフォルトの最大サイズ(2048バイト)のうち、小さい方の値を使用します。sizeを省略した場合、受信するデータグラムの最大サイズは2048バイトとなります。

udp:receiveは、connectedオブジェクト、unconnectedオブジェクトで使用することができます。connectedオブジェクトは接続した相手からのデータだけ受信し、unconnectedオブジェクトは不特定のホストからのデータを受信します。

成功した場合には、受信したデータ(文字列型)を返します。失敗した場合には、nil、エラーメッセージの2つを返します。

こちらの使用例を参照してください。

udp:receivefrom(size)

UDPのオブジェクトudpのメソッドであり、オブジェクトからデータを読み込みます。

sizeには受信するデータグラムの最大サイズを指定します。sizeに指定したデータサイズと、デフォルトの最大サイズ(2048バイト)のうち、小さい方の値を使用します。sizeを省略した場合、受信するデータグラムの最大サイズは2048バイトとなります。

udp:receivefromは、unconnectedオブジェクトで使用することができます。udp:receiveが受信したデータだけを返すのに対して、udp:receivefromは受信したデータの他に、相手先の情報(IPアドレス、ポート番号)も返します。

成功した場合には、受信したデータ(文字列型)、送信元のIPアドレス、ポート番号の3つを返します。失敗した場合には、nil、エラーメッセージの2つを返します。

こちらの使用例を参照してください。

udp:send(datagram)

UDPのオブジェクトudpのメソッドであり、udp:setpeernameで指定した相手へデータを送信します。

datagramには送信するデータを指定します。

UDPの送信はブロックされません。そのため、udp:settimeoutの値に処理が左右されることはありません。

udp:sendは、connectedオブジェクトで使用することができます。

成功した場合、送信したバイト数を返します。失敗した場合には、nil、エラーメッセージの2つを返します。

こちらの使用例を参照してください。

udp:sendto(datagram, ip, port)

UDPのオブジェクトudpのメソッドであり、指定した相手へデータを送信します。

datagramには送信するデータを指定します。

ipおよびportにはデータの送信先ホストのIPv4アドレス、ポート番号を指定します。

UDPの送信はブロックされません。そのため、udp:settimeoutの値に処理が左右されることはありません。

udp:sendtoは、unconnectedオブジェクトで使用することができます。

成功した場合、送信したバイト数を返します。失敗した場合には、nil、エラーメッセージの2つを返します。

こちらの使用例を参照してください。

udp:setpeername(address, port)

UDPのオブジェクトudpのメソッドであり、通信する相手を指定、およびその解除を行います。

addressには、IPv4アドレスまたはホスト名、'*'(アスタリスク)を指定します。'*'を指定した場合、通信相手との対応付けが解除されます。

portには通信する相手のポート番号を指定します。addressに '*' を指定した場合、portの値は無視されます。

udp:setpeernameは、connectedオブジェクト、unconnectedオブジェクトで使用することができます。unconnectedオブジェクトで指定した相手との対応付けが行われると、connectedオブジェクトへ遷移します。また、connectedオブジェクトにおいて、通信相手との対応付けを解除する場合、addressに '*' を指定し、portは省略します。この関数によって通信相手との対応付けが解消されると、unconnectedオブジェクトへと遷移します。

成功した場合、1 を返します。失敗した場合には、nil、エラーメッセージの2つを返します。

こちらの使用例を参照してください。

udp:setsockname(address, port)

UDPのオブジェクトudpのメソッドであり、オブジェクトにローカルアドレスおよびポート番号を割り当てます。

addressには、オブジェクトに割り当てるIPv4アドレス、ホスト名、または'*'(アスタリスク)のいずれかを指定します。'*'を指定した場合、全てのローカルインタフェースに対して関連付けを行います。

portにはオブジェクトに割り当てるポート番号を指定します。portに0を指定した場合、システムが一時的なポートを割り当てます。vRXの場合は49152〜65535、vRX以外の機種の場合は21024〜25000の範囲から割り当てます。

udp:setsocknameは、unconnetedオブジェクトでデータを送信する前に1度だけ使用することができます。また、この関数を省略した場合、UDPでデータを送信するときに、システムが全てのローカルインタフェースに関連付け、一時的なポートの割り当てを行います。

成功した場合、1 を返します。失敗した場合には、nil、エラーメッセージの2つを返します。

こちらの使用例を参照してください。

udp:settimeout(value)

UDPのオブジェクトudpのメソッドであり、オブジェクトのタイムアウト時間を設定します。

valueには、タイムアウトまでの秒数を指定します。nil または負数を指定した場合、処理が完了するまで無期限にブロックします。

タイムアウト時間を設定し指定した時間経過した場合、ブロックしていた関数は処理を中止してエラーを返します。なお、UDPでは、tcp:sendおよびtcp:sendtoはブロックされないため、送信時には本関数による影響は受けません。

udp:settimeoutは、connectedオブジェクト、unconnectedオブジェクトで使用することができます。

成功した場合、1を返します。失敗した場合には、nil、エラーメッセージの2つを返します。

こちらの使用例を参照してください。

rt.mime.b64(data1, data2)

指定されたデータをBase64形式でエンコードして返します。

data1data2にはエンコードするデータ(文字列またはバイナリデータ)を指定します。
data2を指定した場合、data1data2を連結してBase64エンコードを行います。パディングは行わず、エンコードできなかった残りのバイトデータは2つ目の戻り値として返されます。 data2を省略した場合、data1をBase64エンコードします。このとき、data1全体がエンコードされるように必要に応じてパディングを付与します。

Base64エンコードした文字列を返します。data2を指定した場合、エンコードできなかった残りのデータを2つ目の戻り値として返します。
この後にに続くチャンクがある場合、2つ目の戻り値を第一引数のdata1に指定して本関数を呼び出します。

estr = rt.mime.b64("test")
print(estr)
-- estr = dGVzdA==
    

rt.mime.dot(NUM, data)

メッセージに含まれる<CRLF.CRLF>(※)を変換します。
※CRLF:改行を表すコード(アスキーコードでは、CR:0x0D、LF:0x0A)

SMTPでは、<CRLF.CRLF>を送信してメッセージの完了を相手に通知しています。送信メッセージの途中にこのパターンが含まれる場合、メッセージの途中までしか相手は受信しません。本関数では、メッセージ中に改行 CRLFの次にピリオド(.) が続く場合には、直後にもう1つピリオド(.) を追加します。

dataには送信メッセージを指定します。

送信メッセージが複数のブロックに分割されている場合、numには直前のブロックの最後にある文字列のパターンに応じて、次のように数値を指定します。

num 説明
1 直前のブロックの最後の1バイトが CR の場合
2 直前のブロックの最後の2バイトが CRLF の場合
0 上記のどちらにも当てはまらない場合

SMTPのメッセージボディはCRLFから始まるように定義されています。そのため正しいメッセージに変換するためには、本関数を最初にコールする際にnumに 2 を指定しなけれななりません。

変換したメッセージ、dataの末尾にある改行コードの数の2つを返します。2つ目の戻り値である改行コードの数は、末尾がCRの場合は 1、末尾がCRLFの場合は 2となります。末尾がLFの場合でも直前がCRではない場合、2つ目の戻り値は 0 となります。
dataがnilまたは省略された場合には、nil、2 の2つを返します。
この後にに続くチャンクがある場合、2つ目の戻り値を第一引数のnumに指定して本関数を呼び出します。

-- Luaスクリプトでは、CR="\r", LF="\n" と記述します。
dotstr, num = rt.mime.dot(2, ".\r\nSend message.\r\n.\r\n.test\r\n")
print(dotstr)

--[[ 変換後の文字列。CRLFの次に"."が続く場合、"."が追加されている。
..
Send message.
..
..test
]]
    

rt.mime.eol(code, data, marker)

改行コードの変換を行います。

dataには改行コードを変換する文字列を指定します。

送信メッセージが複数のブロックに分割されている場合、codeには直前のブロックの最後にある文字のアスキーコードを指定します。

markerには改行コードを指定します。dataに含まれる改行コードをmarkerで指定した改行コードに置き換えます。markerを省略した場合には、改行コードを<CRLF>に置き換えます。
※ 改行コードとは、次のいずれかを指します。CR, LF, CRLF, LFCR

改行コードを変換した文字列と、2つ目の戻り値には、dataの末尾が改行コードの一部だった場合にはそのアスキーコードを返し、それ以外の場合には 0 を返します。 dataがnilまたは省略された場合には、1つ目の戻り値でnilを返し、2つ目の戻り値は 0 となります。
この後に続くブロックがある場合、2つ目の戻り値を第一引数のcodeに指定して本関数を呼び出します。

-- Luaスクリプトでは、CR="\r", LF="\n" と記述します。
str, num = rt.mime.eol(0, "test\rexample\rtest\r", "\r\n")
print(str)
-- 改行コードを可視化して表示する
print(string.gsub(str, "\r\n", "\\r\\n"))

--[[ 変換結果(コンソールに出力された文字列)
test
example
test

test\r\nexample\r\ntest\r\n     3
]]
    

rt.mime.qp(data1, data2, marker)

指定されたデータをQuoted-Printable形式でエンコードして返します。

data1data2にはエンコードするデータを指定します。
data2を指定した場合、data1data2を連結してQuoted-Printableエンコードを行います。パディングは行わず、エンコードできなかった残りの文字は2つ目の戻り値として返されます。 data2を省略した場合、data1をQuoted-Printableエンコードします。このとき、data1全体がエンコードされるように必要に応じてパディングを付与します。

markerには改行コードを指定します。指定されたデータに含まれる改行コード<CRLF>をmarkerで指定した改行コードに置き換えます。markerを省略した場合には、改行コードを<CRLF>に置き換えます。

Quoted-Printableエンコードした文字列を返します。data2を指定した場合、エンコードできなかった残りのデータを2つ目の戻り値として返します。
この後に続くデータブロックがある場合、2つ目の戻り値を第一引数のdata1に指定し、続くデータブロックをdata2に指定して本関数を呼び出します。

estr, rem = rt.mime.qp("テスト")
print(estr)
-- estr = =83e=83X=83g
    

rt.mime.qpwrp(left_len, data, length)

Quoted-Printableエンコードされた文字列の1行の長さがlengthで指定した長さ以下になるように改行します。

dataにはQuoted-Printableエンコードされた文字列を指定します。

lengthには1行の長さを指定します。lengthを省略した場合、デフォルト値は 76 です。"=XX"のようなQuoted-Printableエンコードされた文字列の途中でlengthで指定した長さに達した場合、Quoted-Printableエンコードされた文字の前で改行します。また、文字列に改行コード(CRLF)が含まれる場合には、1行がlengthの長さ未満であっても、改行コードの位置で改行されます。

送信メッセージが複数のブロックに分割されている場合、left_lenには直前のブロックを本関数で処理した際に出た最終行の余りの長さを指定します。余りの長さは直前のブロックを本関数にて処理した際の2つ目の戻り値として返されます。
処理する文字列が先頭のデータである場合、left_lenには 0 を指定します。

指定した長さで改行された文字列、最終行の余りの長さ(lengthから最終行の長さを引いた値)の2つを返します。dataに続く次のブロックがある場合、2つ目の戻り値を第一引数のleft_lenに指定して本関数を呼び出します。

--Quoted-Printableエンコードされた文字列の配列
-- 「あいうえおかきくけこ」
-- 「さしすせそたちつてと」
tbl = {
 "=82=A0=82=A2=82=A4=82=A6=82=A8=82=A9=82=AB=82=AD=82=AF=82=B1",
 "=82=B3=82=B5=82=B7=82=B9=82=BB=82=BD=82=BF=82=C2=82=C4=82=C6"
}

estr = {}
len = 0
for i, v in ipairs(tbl) do
  estr[i], len = rt.mime.qpwrp(len, v, 16)
end
print(estr[1] .. estr[2])

--[[ 変換結果(コンソールに出力された文字列)
=
=82=A0=82=A2=82=
=A4=82=A6=82=A8=
=82=A9=82=AB=82=
=AD=82=AF=82=B1=
=82=B3=82=B5=82=
=B7=82=B9=82=BB=
=82=BD=82=BF=82=
=C2=82=C4=82=C6
]]
    

rt.mime.unb64(data1, data2)

指定されたデータをBase64形式でデコードして返します。

data1data2にはBase64エンコードされた文字列を指定します。
data2を指定した場合、data1data2を連結してBase64形式でデコードを行います。デコードできなかった残りの文字列は2つ目の戻り値として返されます。 data2を省略した場合、data1をBase64形式でデコードします。

Base64形式でデコードした文字列を返します。data2を指定した場合、デコードできなかった残りの文字列を2つ目の戻り値として返します。
この後に続くブロックがある場合、2つ目の戻り値を第一引数のdata1に指定して本関数を呼び出します。

-- base64エンコードされた文字列をデコードする
estr = "gqKC64LNgsmC2YLWgsY="

str = rt.mime.unb64(estr)
print(str)

--[[ デコードした結果。(コンソールに出力された文字列)
いろはにほへと
]]
    

rt.mime.unqp(data1, data2)

指定されたデータをQuoted-Printable形式でデコードして返します。

data1data2にはQuoted-Printableエンコードされた文字列を指定します。
data2を指定した場合、data1data2を連結してQuoted-Printable形式でデコードを行います。デコードできなかった残りの文字列は2つ目の戻り値として返されます。 data2を省略した場合、data1をQuoted-Printable形式でデコードします。

Quoted-Printable形式でデコードした文字列を返します。data2を指定した場合、デコードできなかった残りの文字列を2つ目の戻り値として返します。
この後に続くブロックがある場合、2つ目の戻り値を第一引数のdata1に指定して本関数を呼び出します。

-- Quoted-Printableエンコードされた文字列をデコードする
data = "=83e=83X=83g"

str = rt.mime.unqp(data)
print(str)

--[[ コンソールへの出力結果
テスト
]]
    

rt.mime.wrp(num, data, length)

文字列をlengthで指定した長さ以下になるように改行します。

dataには指定した長さで改行する文字列を指定します。

lengthには1行の長さを指定します。lengthを省略した場合、デフォルト値は 76 です。lengthで指定した長さで文字列を改行します。また、文字列に改行コード(CRLF)が含まれる場合には、1行がlengthの長さ未満であっても、改行コードの位置で改行されます。

送信メッセージが複数のブロックに分割されている場合、left_lenには直前のブロックを本関数で処理した際に出た最終行の余りの長さを指定します。余りの長さは直前のブロックを本関数にて処理した際の2つ目の戻り値として返されます。
処理する文字列が先頭のデータである場合、left_lenには 0 を指定します。

指定した長さで改行された文字列、最終行の余りの長さ(lengthから最終行の長さを引いた値)の2つを返します。dataに続くブロックがある場合、2つ目の戻り値を第一引数のleft_lenに指定して本関数を呼び出します。

-- 文字列の配列
tbl = {
 "abcdefghijklmnopqrstuvwxyz",
 "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
 "0123456789"
}

estr = {}
len = 0
for i, v in ipairs(tbl) do
  estr[i], len = rt.mime.wrp(len, v, 10)
end

print(estr[1] .. estr[2] .. estr[3])


--[[ 改行された結果。(コンソールに出力された文字列)

abcdefghij
klmnopqrst
uvwxyzABCD
EFGHIJKLMN
OPQRSTUVWX
YZ01234567
89
]]
    

OS

os.clock()

実行中のLuaスクリプトが開始されてから現在の時刻までの秒数を返します。

Lua言語の標準仕様ではos.clockは実行中のLuaスクリプトで消費されたCPU時間のおおよその秒数を返すことになっていますが、ヤマハルーターの実装は異なっています。この実装は将来、標準仕様に変更される可能性があります。
t1 = os.clock()
do
  … -- 時間のかかる処理
end
t2 = os.clock()
print("実行時間", t2 - t1) -- 実行時間の表示
    

os.date(format, time)

指定された時刻を表す文字列またはテーブルを返します。timeは、os.timeの戻り値であり、これがあるときにはその時刻を対象とします。timeが省略された場合は、関数が呼び出されたときの現在時刻を対象とします。

formatは、時刻の戻り値への変換方法を定義します。

formatの先頭が'!'であるときには、時刻はUTC(協定世界時)として変換されます。それ以外の場合には、timezoneコマンドで指定されたタイムゾーンの時刻として変換されます。

先頭にあるかもしれない'!'を取り除いた後のformatが、"*t"という文字列である場合には、時刻は以下の文字列をキーとする要素を持つテーブルへと変換されます。

format"*t"以外の形であるときには、C言語のstrftime関数のフォーマット文字列として動作します。

formatを省略した場合には、"%c"が与えられたものとして現在時刻を文字列に変換します。

os.difftime(time2, time1)

時刻time1からtime2までの経過時間を秒で返します。time1time2ともに、os.timeの戻り値でなければなりません。

t1 = os.time()
do
  … -- 時間のかかる処理
end
t2 = os.time()
print("実行時間", os.difftime(t2, t1)) -- 実行時間の表示
    

os.exit([code])

Luaスクリプトの実行を終了します。codeは終了コードであり、0が正常終了です。この関数は呼び出し元には戻ってきません。

function f(x)
  if x < 1 or x > 100 then
    print("Error")
    os.exit(0)
  end
…
end
    

os.getenv(varname)

環境変数varnameの値を文字列で返します。varnameが定義されていないときはnilを返します。

user = os.getenv("USER")
if user then
  print("USER:", user)
else
  print("USER: undefined")
end
    

os.remove(filename)

filenameで指定したファイルを削除します。ディレクトリを削除する場合は、中が空になっていないといけません。

ファイルを削除できた場合はtrueが、失敗した場合はfalseとエラーメッセージ(文字列)が返ります。

os.remove("FILE.txt")
    

os.rename(oldname, newname)

oldnameで指定したファイルのファイル名をnewnameに変更します。ファイルが存在するディレクトリは変更できません。

ファイル名を変更できた場合はtrueが、失敗した場合はfalseとエラーメッセージ(文字列)が返ります。

os.rename("FILE.txt", "NEW-FILE.txt")
    

os.time(tbl)

指定された時刻を表す数値で、「1980年1月1日 9時0分0秒」からの経過秒数を返します。tblは時刻を表すテーブルで、必須の要素として、yearmonthdayを持っていなければなりません。また、hourminsecを持つこともできます。isdstはあっても無視されます。各要素の意味は、os.dateを参照してください。tblが省略された場合は、関数が呼び出されたときの現在時刻を返します。

os.timeの戻り値は、os.dateおよびos.difftimeの引数としてのみ、意味を持ちます。

t1 = os.time()
do
  … -- 時間のかかる処理
end
t2 = os.time()
print("実行時間", os.difftime(t2, t1)) -- 実行時間の表示
    

モジュール

モジュールとは、ライブラリ関数を提供するための機構です。この文書で説明しているライブラリ関数群も、多くはモジュールの機構で提供されています。

ユーザーが新規にモジュールを作成する場合は、モジュールファイルを作成する必要があります。モジュールファイルは通常のLuaスクリプトですが、以下の点が異なります。

このようになっているモジュールファイルは、他のLuaスクリプトからrequire関数で読み込むことができ、モジュールファイルで定義したライブラリ関数等を利用できるようになります。

ヤマハルーターの実装では、C言語で記述したモジュールを作成、呼び出すことはできません。

module(name, func...)

モジュールを作成します。通常、モジュールファイルの先頭でmodule関数を呼び出し、ファイルをモジュールファイルとします。

文字列nameはモジュールの名前です。通常は、モジュールファイルの名前から拡張子(.lua)を削除したものと同じ名前にしておきます。

グローバル環境下でnameを名前とするテーブルが新たに作成され、そのテーブルがモジュールファイルの新しい環境となります。これにより、モジュールファイル内で定義した関数等は、requireでモジュールを読み込んだLuaスクリプトからは、nameの要素としてアクセスできることになります。

[ルーターコマンド]
set LUA_PATH="/lua/module/\?.lua;"
set PWD="/lua"

[/lua/module/mod1.lua]
module("mod1")
value = 100
function func(x)
  return x + 1
end

[/lua/script.lua]
require("mod1")
print(mod1.value) -- モジュールmod1の変数valueを表示
x = mod1.func(10) -- モジュールmod1の関数funcを呼び出し
    

funcは、環境の切り替え後に作成されたモジュールを引数として呼び出されます。funcは0個以上、任意の数が指定できます。

moduleは環境をグローバル環境から独自の環境に切り替えます。一般のライブラリ関数はグローバル環境に名前が登録されているため、そのままではモジュールファイルの中では利用できません。それを避けるために、funcpackage.seeall関数を指定すると、package.seeallの効果でモジュールファイルの中でも一般ライブラリ関数が使用できるようになります。

[ルーターコマンド]
set LUA_PATH="/lua/module/\?.lua;"
set PWD="/lua"

[/lua/module/mod2.lua]
module("mod2", package.seeall)
function func(x)
  return string.format("%08x", x) -- package.seeallの効果でライブラリ関数が呼び出せる
end

[/lua/script.lua]
require("mod2")
x = mod2.func(10) -- モジュールmod2の関数funcを呼び出し
    

require(name)

モジュールファイルを読み込みます。nameはモジュール名であり、モジュールファイルの名前の一部です。

モジュールファイルは、環境変数LUA_PATHにしたがって探索されます。LUA_PATHは、複数の場所をセミコロン(;)で区切って並べ、先頭から探索します。個々の場所の探索では、LUA_PATH中の文字(?)をnameで指定したモジュール名で置き換えてファイルがあるかどうかを探索します。

たとえば、モジュール名"foo"を以下のLUA_PATHで探索する場合、./foo.lua/lua/module/foo.lua/lua/module/foo/init.luaの順にファイルを探します。

set LUA_PATH="./\?.lua;/lua/module/\?.lua;/lua/module/\?/init.lua"
    

package.seeall(name)

モジュールnameの中から一般ライブラリ関数が呼び出せるようにします。moduleの2番目以降の引数として指定することで機能を果たします。

コルーチン

Lua言語では言語レベルでコルーチンをサポートしており、coroutine.*ライブラリ関数群を通して利用できます。コルーチンはイテレータ、無限リストなどの継続状況を持つプログラムの記述を容易にします。

以下は、フィボナッチ数列を求めるのにコルーチンを使用した例です。フィボナッチ数列を求める関数はその定義から再帰を用いて簡潔に記述できますが、順列を追っていくと再帰呼び出しの回数が爆発的に増えるためにあまり実用的ではありません。コルーチンを使用すれば、無限に順列を追っていくことができます。

-- 以下は、フィボナッチ数列を再帰で求める関数

function fib(n)
  if n < 2 then
    return n
  else
    return fib(n - 1) + fib(n - 2)
  end
end

-- 以下の関数は、n以下のフィボナッチ数列を順に返す関数を戻り値とする

function generatefib(n)
  return coroutine.wrap(function ()
    local a, b = 1, 1
    while a <= n do
      coroutine.yield(a)
      a, b = b, a + b
    end
  end)
end

-- 1000以下のフィボナッチ数列を出力する
for i in generatefib(1000) do print(i) end
    

coroutine.create(func)

関数funcを本体とするコルーチンを作成し、そのコルーチン(スレッド型)を返します。

coroutine.resume(co, val1,...)

コルーチンcoを開始、または再開します。最初にcoroutine.resumeを呼んだ場合はコルーチンの開始であり、コルーチンの本体である関数が、val1, ...を引数として呼ばれます。中断されているコルーチンに対してcoroutine.resumeを呼んだ場合はコルーチンの再開であり、val1, ...coroutine.yieldの戻り値になります。

コルーチンの実行中にエラーが発生しなければ、coroutine.resumeは、最初の戻り値としてtrue、引き続く戻り値としてcoroutine.yieldの引数か、あるいは本体の関数の戻り値を返します。コルーチンの実行中にエラーが発生した時は、最初の戻り値としてfalse、2番目の戻り値にエラーメッセージの文字列を返します。

coroutine.running()

動作中のコルーチン(スレッド型)を返します。動作中のコルーチンがない場合はnilを返します。

coroutine.status(co)

コルーチンcoの状態を文字列で返します。

coroutine.wrap(func)

関数funcを本体とするコルーチンを作成し、そのコルーチンを再開する関数を返します。戻り値の関数に与えられた引数は、coroutine.resumeと同じ意味を持ちます。戻り値はcoroutine.resumeのそれから最初の論理型を除いたものになります。コルーチンの実行中にエラーが発生したときは、エラーが伝播します。すなわち、スクリプト全体がエラーで停止します。

coroutine.yield(...)

コルーチンの実行を中断します。与えられた引数は、coroutine.resumeの戻り値となります。また、新しく再開するために呼び出されたcoroutine.resumeの引数が、coroutine.yieldの戻り値となります。


←前 目次
次→