6.4 文字列操作

このライブラリは部分文字列の検索・抽出やパターンマッチングといった文字列操作のための一般的な関数を提供します。Lua で文字列にアクセスするときのインデックスは最初の文字が 1 です (C のように 0 ではありません)。負のインデックスも使うことができ、文字列の最後から始まって後ろ向きに進んだ位置として解釈されます。例えば文字列の最後の文字にはインデックス -1 でアクセスできます。

文字列ライブラリの関数は全て string というテーブルの中に提供されます。また文字列ライブラリは文字列型のメタテーブルの __index フィールドに string テーブルを設定するので、文字列ライブラリの関数はオブジェクト指向のスタイルで呼び出すことができます。例えば string.byte(s,i)s:byte(i) とできます。

文字列ライブラリは一バイトで一文字を表すエンコーディングを仮定します。

string.byte (s [, i [, j]])

文字 s[i], s[i+1], ..., s[j] を表す内部数値コードを返します。i のデフォルト値は 1 で、j のデフォルト値は i です。インデックスは string.sub と同じ規則に従って修正されます。

数値コードがプラットフォーム間でポータブルであるとは限りません。

string.char (...)

ゼロ個以上の整数を受け取ります。返り値は文字列であり、長さが引数の数と等しく、各文字の内部数値コードが同じ位置の引数と一致します。

数値コードがプラットフォーム間でポータブルであるとは限りません。

string.dump (function [, strip])

与えられた関数のバイナリ表現 (バイナリチャンク) を表す文字列を返します。この文字列を load すると関数のコピー (のアップバリューを新しくしたもの) が返ります。striptrue にすると、バイナリ表現から関数のデバッグ情報を削除して容量を節約することが許可されます。

アップバリューを持つ関数のバイナリ表現にはアップバリューの数だけが保存され、(再) 読み込み時にはこれらのアップバリューに新しいインスタンスが与えられます。アップバリューの初期化に関して詳しくは load を参照してください。またデバッグライブラリを使えば関数のアップバリューの再読み込みを好きな方法で行えます。

string.find (s, pattern [, init [, plain]])

文字列 s に含まれるパターン pattern の最初のマッチを検索します (参照: § 6.4.1)。マッチが見つかった場合には、マッチの始まりと終わりを示す s のインデックスが返ります。見つからなければ fail が返ります。三つ目の省略可能な数値引数 init は検索を始める場所を表します。デフォルト値は 1 であり、負の値も許されます。第四引数 plain も省略可能であり、これを ture とするとパターンマッチの機能が無効化されます。このときは単純な部分文字列の検索が行われ、pattern に含まれる特殊文字は通常の文字として処理されます。

キャプチャを持つパターンのマッチが成功した場合には、二つのインデックスの後にキャプチャされた値も返ります。

string.format (formatstring, ...)

第一引数の文字列で表されるフォーマットに従って、後ろに続く可変個数の引数を文字列に変換します。値から文字列への変換は基本的に ISO C の sprintf と同様です。異なるのは変換指定子 (および修飾子) の *, h, L, l, n が使えないこと、そして q という Lua 特有の指定子が使えることです。

変換指定子 q は真偽値・nil・数値・文字列を Lua ソースコードに埋め込める文字列に変換します。真偽値と nil はそのまま (つまり "true", "false", "nil" に) 変換されます。浮動小数点は精度を保つために 16 進数で書かれます。文字列はダブルクオートで囲まれ、Lua インタープリタが正しく読めるよう必要に応じてエスケープを行いながら出力されます。例えば、

string.format('%q', 'a string with "quotes" and \n new line')

が出力する文字列の一例は次の通りです:

"a string with \"quotes\" and \
 new line"

指定子 q は修飾子 (フラグ・幅・長さ) をサポートしません。

変換指定子 A, a, E, e, f, G, g は全て数値を引数に取ります。また変換指定子 c, d, i, o, u, X, x が期待するのは整数です。Lua が C89 コンパイラでコンパイルされた場合には、Aa (16 進浮動小数点数) は修飾子をサポートしません。

変換指定子 s は文字列を受け取ります。引数が文字列でない場合には tostring と同じ規則で文字列に変換されます。修飾子が付いていない指定子 s に対応する文字列はゼロ文字を含むべきではありません。

変換指定子 plua_topointer が返すポインタを受け取ります。この指定子を使うと、テーブル・ユーザーデータ・スレッド・文字列・関数に対するユニークな文字列識別子が得られます。他の値 (数値・nil・真偽値) に対する lua_topointer の返り値をこの指定子に渡すと、NULL ポインタを表す文字列となります。

string.gmatch (s, pattern [, init])

呼び出すたびに文字列 s に含まれる pattern のキャプチャを一つずつ返す関数を返します (参照: § 6.4.1)。pattern にキャプチャを指定しなければ、返り値の関数は呼び出すたびにマッチ全体を返します。三つ目の省略可能な数値引数 init は探索を始める場所を表します。デフォルトは 1 で、負でも構いません。

例えば次のループは文字列 s に含まれる単語をイテレートする処理であり、各単語が一行ごとに表示されます:

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

次の例は与えられた文字列に含まれる key=value という形のペアをテーブルに格納します:

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

この関数ではパターンの最初にキャレット '^' があってもアンカーとして機能することはありません。アンカーを含むパターンが複数回マッチすることはあり得ないためです。

string.gsub (s, pattern, repl [, n])

s をコピーし、コピーに含まれる全ての (n が与えられるなら n 個の) パターン patternrepl で「置き換えた」文字列を返します (参照: § 6.4.1)。repl は文字列・テーブル・関数のいずれかです。この他に gsub は二つ目の返り値としてマッチの総数を返します。gsub という名前は「グローバル置換 (Global SUBstitution)」から来ています。

repl が文字列なら、その値が置換後の文字列として使われます。そのとき文字 % はエスケープ文字として機能します: 1 から 9 の d に対するシーケンス %d はキャプチャされた d 番目の文字列を表し、%0 はマッチ全体を表します。単一の %%% というシーケンスで表されます。

repl がテーブルなら、マッチごとに一つ目のキャプチャをキーとしてテーブルが検索されます。

repl が関数なら、マッチごとにキャプチャされた全ての部分文字列を引数として関数が呼ばれます。

いずれの場合でも、パターンにキャプチャがないときはパターン全体が一つのキャプチャに含まれるものとして振る舞います。

テーブルの検索および関数の呼び出しが返した値が文字列または数値の場合には、それが置換文字列として使われます。返り値が false または nil の場合には置換文字列は無いものとして扱われます (マッチは元の文字列のままとなります)。

いくつか例を示します:

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

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

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

x = string.gsub("home = $HOME, user = $USER", "%$(%w+)", os.getenv)
--> x="home = /home/roberto, user = roberto"

x = string.gsub("4+5 = $return 4+5$", "%$(.-)%$", function (s)
      return load(s)()
    end)
--> x="4+5 = 9"

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

string.len (s)

文字列を受け取ってその長さを返します。空文字列 "" の長さは 0 です。文字列中のゼロ文字も長さに含めるので、例えば "a\000bc\000" の長さは 5 です。

string.lower (s)

受け取った文字列をコピーし、コピーに含まれる大文字を小文字にして返します。大文字でない文字は変更されずそのままです。「大文字」の定義は現在のロケールに依存します。

string.match (s, pattern [, init])

文字列 s で最初に見つかるパターン patternマッチを返します (参照: § 6.4.1)。マッチが見つかればマッチのキャプチャを返し、見つからなければ fail を返します。キャプチャを持たない pattern では、マッチ全体が返り値となります。三つ目の省略可能な数値引数 init は検索を始める位置を表します。デフォルトは 1 で、負の値を使うこともできます。

string.pack (fmt, v1, v2, ...)

フォーマット文字列 fmt に従って値 v1, v2, ... をバイナリ形式にシリアライズ (パック) し、その結果のバイナリ文字列を返します。フォーマット文字列については § 6.4.2 を参照してください。

string.packsize (fmt)

与えられたフォーマット文字列を使って string.pack を実行したときに返る文字列の長さを返します。このフォーマット文字列には sz のような可変長のオプションを含めることができません。フォーマット文字列については § 6.4.2 を参照してください。

string.rep (s, n [, sep])

n 個の文字列 ssep で繋いだ文字列を返します。デフォルトの sep は空文字列であり、このとき隣り合う s の間に区切りはありません。n が正でないときは空文字列を返します。

(この関数を一度呼び出すだけで非常に簡単にマシンのメモリを使い切ってしまえることに注意してください)

string.reverse (s)

文字列 s を反転させた文字列を返します。

string.sub (s, i [, j])

si 文字目で始まり j 文字目で終わる部分文字列を返します。ij に負の値を指定することもできます。j が与えられなかった場合には -1 とみなされます (文字列の長さと同じ意味です)。例えば string.sub(s,1,j)s の最初から j 文字を返し、正の i に対する string.sub(s,-i) は最後の i 文字を返します。

負の ij を変換した後、i が 1 より小さければ 1 に修正され、j が文字列の長さより大きければ文字列の長さに修正されます。この修正の後に ij より大きければ、空文字列が返ります。

string.unpack (fmt, s [, pos])

フォーマット文字列 (§ 6.4.2) fmt に従って文字列 s に埋め込まれた値を返します (参照: string.pack)。

string.upper (s)

受け取った文字列をコピーし、コピーに含まれる小文字を全て大文字に変更した文字列を返します。小文字以外の文字は変更されずにそのままです。「小文字」の定義は現在のロケールに依存します。

6.4.1. パターン

Lua におけるパターン (pattern) は正規表現によって表され、パターンマッチを行う関数 string.find, string.gmatch, string.gsub, string.match で使われるパターンとして解釈されます。この節ではパターンを表す文字列の構文および意味 (何にマッチするのか) を説明します。

文字クラス

文字クラス (character class) は文字の集合を表すのに利用されます。Lua で文字クラスの記述に利用できる文字の組み合わせは次の通りです:

小文字を使って表されるクラス (%a, %c, ...) で大文字を使うと、元のクラスの補集合が表されます。例えば %S は空白でない文字を表します。

「文字」や「空白」といった文字グループの定義は現在のロケールに影響を受けます。例えば [a-z]%l は一致しない可能性があります。

パターンアイテム

パターンアイテム (pattern item) は次のいずれかです:

パターン

パターン (pattern) はパターンアイテムを並べたものです。キャレット (^) がパターンの最初にあると、マッチが対象の文字列の先頭に固定されます。また $ がパターンの最後にあると、マッチが対象の文字列の末尾に固定されます。これ以外の場所にある ^$ は特殊な意味を持たず、文字そのものを表します。

キャプチャ

パターンの中に括弧で囲われた部分パターンがあると、それはキャプチャ (capture) となります。マッチが成功すると、キャプチャにマッチした対象文字列の部分文字列が保存され (キャプチャされ)、後で使えるようになります。キャプチャは括弧開きの位置に応じて番号が付きます。例えば "(a*(.)%w(%s*))" というパターンでは "a*(.)%w(%s*)" にマッチする部分文字列が最初のキャプチャとして保存され、"." にマッチするのが二つ目のキャプチャ、"%s*" にマッチするのが三つ目のキャプチャとなります。これらのキャプチャにはそれぞれ 1, 2, 3 の番号が付きます。

特別な場合として、() というキャプチャは文字列における現在位置を表す数字をキャプチャします。例えばパターン "()aa()" を文字列 flaaap に適用すると、3 と 5 が保存された二つのキャプチャが作られます。

複数マッチ

関数 string.gsub とイテレータ string.gmatch は対象文字列に含まれるパターンのマッチを複数個見つけます。こういった場合には、新しいマッチは一つ前のマッチの終わりから少なくとも一バイト離れて終わる場合に限って有効とみなされます。言い換えると、あるマッチの直後にある空文字列にパターンがマッチすることはありません。例として次を考えます:

> string.gsub("abc", "()a*()", print);
--> 1   2
--> 3   3
--> 4   4

二つ目と三つ目の返り値はそれぞれ bc の後にある空文字列とのマッチに対応します。a の後にある空文字列とマッチしないのは、この空文字列が前回のマッチと同じ位置で終わっているからです。

6.4.2. pack と unpack のフォーマット文字列

string.pack, string.packsize, string.unpack は第一引数にフォーマット文字列を受け取ります。これは作成あるいは読み込みの対象となるデータのレイアウトを記述する文字列です。

フォーマット文字列は変換オプションを並べたものであり、利用できるオプションは次の通りです ([n] は省略可能な整数値を表します):

パディング・空白・設定に関するオプション ("xX <=>!") を除いた各オプションは string.pack の引数および string.unpack の返り値に対応します。

オプション "!n", "sn", "in", "In"n は 1 から 16 までの整数です。整数の値に対してはオーバーフローのチェックが行われます。つまり string.pack は引数が指定されたサイズに収まることを確認し、string.unpack は読み込んだ値が Lua の整数に収まることを確認します。

任意のフォーマット文字列は先頭に "!1=" があるものとして処理されます。つまり最大アラインメントは 1 (アラインメント無し) で、エンディアンはネイティブです。

ネイティブなエンディアンを使う処理ではシステム全体がビッグエンディアンまたはリトルエンディアンであることが仮定されます1string.packstring.unpack はエンディアンが混ざるフォーマット文字列に対して正しく動作しません。

アラインメントは次のように処理されます: 各オプションについて、オプションが要求するサイズと最大アラインメントの最小値の倍数で始まるデータまでパディングが追加されます。この最小値は 2 のべきである必要があります。オプション "c""z" はアラインされず、オプション "s" は最初の整数のアラインメントに従います。

パディングは string.pack ではゼロ埋めされ、string.unpack では無視されます。


  1. 訳注: マシンのエンディアンを実行中に切り替えると正しく動かないということ。非常に古いマシンにはこの機能を持つものが存在した。Lua のフォーラム (http://lua.2524044.n2.nabble.com/NoW-A-question-about-mixed-endianness-td7685791.html) に関連する議論がある。[return]