この初版はLua 5.0向けに書かれました。後続のバージョンでも大部分は関連性がありますが、いくつかの違いがあります。
第4版はLua 5.3を対象としており、Amazonおよびその他の書店で入手できます。
本書を購入することで、Luaプロジェクトの支援にもなります。
![]() |
プログラミング inLua | ![]() |
第III部 標準ライブラリ 第20章 文字列ライブラリ |
文字クラスを使用すると、パターンをより役立つものにすることができます。文字クラスとは、特定の集合内の任意の文字にマッチできるパターン内の要素です。たとえば、クラス`%d`は任意の数字にマッチします。したがって、`dd/mm/yyyy`形式の日付を`'%d%d/%d%d/%d%d%d%d'`というパターンで検索できます。
s = "Deadline is 30/05/1999, firm" date = "%d%d/%d%d/%d%d%d%d" print(string.sub(s, string.find(s, date))) --> 30/05/1999次の表に、すべての文字クラスを示します。
. | すべての文字 |
%a | 英字 |
%c | 制御文字 |
%d | 数字 |
%l | 小文字 |
%p | 句読点 |
%s | 空白文字 |
%u | 大文字 |
%w | 英数字 |
%x | 16進数 |
%z | 表現0の文字 |
これらのクラスの大文字バージョンは、クラスの補集合を表します。たとえば、`%A`はすべての英字以外の文字を表します。
print(string.gsub("hello, up-down!", "%A", ".")) --> hello..up.down. 4(`4`は結果の文字列の一部ではありません。これは`gsub`の2番目の結果であり、置換の総数です。`gsub`の結果を出力する他の例では、このカウントは省略されます。)
いくつかの文字はマジック文字と呼ばれ、パターンで使用されると特別な意味を持ちます。マジック文字は次のとおりです。
( ) . % + - * ? [ ^ $文字`%`は、これらのマジック文字のエスケープとして機能します。そのため、`%.`はドットにマッチし、`%%`は文字`%`自身にマッチします。エスケープ`%`は、マジック文字だけでなく、他のすべての英数字以外の文字にも使用できます。疑わしい場合は、安全を期してエスケープを使用してください。
Luaでは、パターンは通常の文字列です。特別な処理はなく、他の文字列と同じルールに従います。関数内でのみパターンとして解釈され、その時点で`%`がエスケープとして機能します。したがって、パターン内に引用符を入れる必要がある場合は、他の文字列内に引用符を入れるのと同じテクニックを使用する必要があります。たとえば、Luaのエスケープ文字である`\`を使用して引用符をエスケープできます。
文字集合を使用すると、角括弧の間に異なるクラスと単一の文字を組み合わせて、独自の文字クラスを作成できます。たとえば、文字集合`[%w_]`は英数字とアンダースコアの両方にマッチし、文字集合`[01]`は2進数にマッチし、文字集合`[%[%]]`は角括弧にマッチします。テキスト中の母音の数を数えるには、次のように記述できます。
_, nvow = string.gsub(text, "[AEIOUaeiou]", "")文字集合には、範囲内の最初の文字と最後の文字をハイフンで区切って文字範囲を含めることもできます。ほとんどの便利な範囲は既に定義されているため、この機能が必要になることはほとんどありません。たとえば、`[0-9]`は`%d`と記述する方が簡単で、`[0-9a-fA-F]`は`%x`と同じです。ただし、8進数の数字を見つける必要がある場合は、明示的な列挙(`[01234567]`)ではなく、`[0-7]`を優先する場合があります。文字集合の先頭に`^`を付けることで、文字集合の補集合を取得できます。`[^0-7]`は8進数ではない任意の文字を見つけ、`[^\n]`は改行以外の任意の文字にマッチします。ただし、大文字バージョンを使用して単純なクラスを否定することもできます。`%S`は`[^%s]`よりも簡単です。
文字クラスは、Luaに設定されている現在のロケールに従います。そのため、クラス`[a-z]`は`%l`とは異なる場合があります。適切なロケールでは、後者の形式には`ç`や`ã`などの文字が含まれます。他に特別な理由がない限り、常に後者の形式を使用する必要があります。よりシンプルで、移植性が高く、わずかに効率的です。
繰り返しとオプションの部分に対する修飾子を使用すると、パターンをさらに役立つものにすることができます。Luaのパターンには、4つの修飾子が用意されています。
+ | 1回以上の繰り返し |
* | 0回以上の繰り返し |
- | これも0回以上の繰り返し |
? | オプション(0回または1回) |
`+`修飾子は、元のクラスの1文字以上の文字にマッチします。常にパターンにマッチする最長のシーケンスを取得します。たとえば、パターン`%a+`は1文字以上の英字、つまり単語を意味します。
print(string.gsub("one, and two; and three", "%a+", "word")) --> word, word word; word wordパターン`%d+`は1つ以上の数字(整数)にマッチします。
i, j = string.find("the number 1298 is even", "%d+") print(i,j) --> 12 15
`*`修飾子は`+`に似ていますが、クラスの文字が0回発生する場合にも受け入れます。一般的な用途は、パターンの部分間のオプションの空白にマッチすることです。たとえば、`()`や`( )`などの空の括弧のペアにマッチするには、`%(%s*%)`というパターンを使用します。(パターン`%s*`は0個以上の空白にマッチします。括弧はパターン内で特別な意味を持つため、`%`でエスケープする必要があります。)別の例として、パターン`[_%a][_%w]*`はLuaプログラムの識別子にマッチします。これは、英字またはアンダースコアで始まり、0個以上のアンダースコアまたは英数字が続くシーケンスです。
`*`と同様に、`-`修飾子も元のクラスの文字を0回以上繰り返してマッチします。ただし、最長のシーケンスにマッチするのではなく、最短のシーケンスにマッチします。場合によっては、`*`と`-`の違いはありませんが、通常は異なる結果になります。たとえば、パターン`[_%a][_%w]-`を使用して識別子を見つけようとすると、`-`は常に空のシーケンスにマッチするため、最初の文字のみが見つかります。一方、Cプログラムのコメントを見つけたいとします。多くの人が最初に`/%*.*%*/`を試みます(つまり、適切なエスケープで記述された`/*"`, 任意の文字のシーケンス、`*/`)。ただし、`.*`は可能な限り展開されるため、プログラム内の最初の`/*" `は最後の`*/`でのみ閉じられます。
test = "int x; /* x */ int y; /* y */" print(string.gsub(test, "/%*.*%*/", "<COMMENT>")) --> int x; <COMMENT>一方、パターン`.-`は、最初の`*/`を見つけるために必要な最小限に展開されるため、目的の結果が得られます。
test = "int x; /* x */ int y; /* y */" print(string.gsub(test, "/%*.-%*/", "<COMMENT>")) --> int x; <COMMENT> int y; <COMMENT>
最後の修飾子`?`は、オプションの文字にマッチします。例として、テキスト中の整数を見つけたいとします。この数は、オプションの符号を含んでいる場合があります。パターン`[+-]?%d+`は、`"-12"`、`"23"`、`"+1009"`などの数字にマッチし、機能します。`[+-]`は`+`または`-`のどちらにもマッチする文字クラスであり、続く`?`はその符号をオプションにします。
他のシステムとは異なり、Luaでは修飾子は文字クラスにのみ適用できます。修飾子の下でパターンをグループ化する方法はできません。たとえば、(単語に1文字しかない場合を除き)オプションの単語にマッチするパターンはありません。通常、後で説明する高度なテクニックのいくつかを使用して、この制限を回避できます。
パターンが`^`で始まる場合、対象文字列の先頭でのみマッチします。同様に、`$`で終わる場合は、対象文字列の末尾でのみマッチします。これらのマークは、検索するパターンを制限し、パターンをアンカーするために使用できます。たとえば、テスト
if string.find(s, "^%d") then ...は、文字列`s`が数字で始まるかどうかをチェックし、テスト
if string.find(s, "^[+-]?%d+$") then ...はその文字列が他の先頭または末尾の文字のない整数であるかどうかをチェックします。
パターンのもう1つの要素は`%b`であり、バランスの取れた文字列にマッチします。このような要素は`%bxy`と記述され、ここで`x`と`y`は任意の2つの異なる文字です。`x`は開始文字として機能し、`y`は終了文字として機能します。たとえば、パターン`%b()`は、`(`で始まり、対応する`)`で終わる文字列の部分にマッチします。
print(string.gsub("a (enclosed (in) parentheses) line", "%b()", "")) --> a line通常、このパターンは`%b()`、`%b[]`、`%b%{}`、または`%b<>`として使用されますが、区切り文字として任意の文字を使用できます。
Copyright © 2003–2004 Roberto Ierusalimschy. All rights reserved. | ![]() |