0Pricing
Lua Academy · レッスン

部分文字列の検索と抽出

string.findとstring.subを使ってテキストを検索・抽出します。

「部分文字列の検索と抽出」はCoddyKit上の無料Lua Academyレッスンです。 これはレッスン2/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはLua Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Lua Academyコースには全4レッスンが含まれています。

string.find の基本

string.find(s, pattern, init, plain)は、init(デフォルトは1)の位置からs内のパターンを検索します。一致した部分の開始位置と終了位置を返し、見つからない場合はnilを返します。plain=trueを指定すると、パターンをリテラル文字列として扱い、マジック文字を解釈しません。

local s = "hello world"
local i, j = string.find(s, "world")
print(i, j)    -- 7  11

-- Plain search (literal string)
local i2, j2 = string.find("a+b=5", "+", 1, true)
print(i2, j2)  -- 2  2

-- Not found
print(string.find(s, "xyz"))  -- nil

抽出に使う string.sub

string.sub(s, i, j)は、位置iからjまで(両端を含む)の部分文字列を抽出します。負のインデックスは末尾から数えます。-1は最後の文字を表します。jを省略した場合は、文字列の末尾がデフォルトになります。

local s = "hello world"
print(string.sub(s, 1, 5))    -- hello
print(string.sub(s, 7))       -- world
print(string.sub(s, -5))      -- world
print(string.sub(s, 1, -7))   -- hello
print(s:sub(7, 11))           -- world (method syntax)

find と sub の組み合わせ

string.findとstring.subを組み合わせて、部分文字列の位置を特定し、抽出します。まず区切り文字を検索し、その周辺にある各部分を抽出します。これは文字列を分割する基本的な方法です。

local s = "key=value"
local i = string.find(s, "=")
if i then
  local key = string.sub(s, 1, i - 1)
  local val = string.sub(s, i + 1)
  print(key, val)   -- key  value
end

パターンキャプチャに使う string.match

string.match(s, pattern, init)は、パターンに一致したキャプチャ済みの部分文字列を返します。パターンにキャプチャがない場合は、一致した全体を返します。一致するものがない場合はnilを返します。キャプチャはパターン内で括弧を使って定義します。

local date = "2024-03-15"
local y, m, d = string.match(date, "(%d+)-(%d+)-(%d+)")
print(y, m, d)   -- 2024  03  15

-- No capture: returns the whole match
local num = string.match("price: 42.5 USD", "%d+%.%d+")
print(num)       -- 42.5

最後の出現箇所を検索する

部分文字列の最後の出現箇所を見つけるには、開始位置を進めながらループで検索するか、末尾から検索します。標準的な方法は、前回の一致箇所の直後の位置を指定してstring.findを呼び出し、nilが返るまで繰り返すことです。

local function findLast(s, sub)
  local last_i, last_j
  local i, j = string.find(s, sub, 1, true)
  while i do
    last_i, last_j = i, j
    i, j = string.find(s, sub, j + 1, true)
  end
  return last_i, last_j
end

local i, j = findLast("a/b/c/d", "/")
print(i, j)   -- 6  6

ファイル拡張子の抽出

string.matchの実用例として、ファイル名から拡張子を抽出できます。パターン"([^%.]+)$"は、文字列末尾にある最後のドット以外の連続した部分をキャプチャします。最後のドットの直後だけをキャプチャするには、"%.([^%.]+)$"を使います。

local function getExt(filename)
  return string.match(filename, "%.([^%.]+)$")
end

print(getExt("photo.jpg"))        -- jpg
print(getExt("archive.tar.gz"))   -- gz
print(getExt("README"))           -- nil
print(getExt("config.lua.bak"))   -- bak

文字列の分割

Luaには組み込みの文字列分割機能はありませんが、string.gmatchを使って実装できます。区切り文字以外のすべての連続部分を反復処理するか、区切り文字の間をキャプチャするパターンを使用します。

local function split(s, sep)
  local result = {}
  local pattern = "([^" .. sep .. "]+)"
  for part in string.gmatch(s, pattern) do
    result[#result+1] = part
  end
  return result
end

local parts = split("one,two,three,four", ",")
for i, p in ipairs(parts) do
  print(i, p)
end
-- 1 one  2 two  3 three  4 four

空白のトリミング

先頭と末尾の空白は、空白に一致させて破棄することで削除できます。パターン"^%s*(.-)%s*$"は、遅延量指定子.-を使い、先頭と末尾にある省略可能な空白の間の最小限の内容をキャプチャします。

local function trim(s)
  return string.match(s, "^%s*(.-)%s*$")
end

print("|" .. trim("  hello  ") .. "|")  -- |hello|
print("|" .. trim("  \t\n") .. "|")    -- ||
print("|" .. trim("no spaces") .. "|")  -- |no spaces|

テキストから数値を抽出する

数値用のパターンとともにstring.gmatchを使うと、文字列からすべての数値を抽出できます。パターン%-?%d+%.?%d*は、任意の負号、数字、任意の小数点、続く数字に一致します。

local text = "Revenue: $1,234.56 Expenses: $567.89 Net: $666.67"
local numbers = {}
for n in string.gmatch(text, "%d+%.?%d*") do
  numbers[#numbers+1] = tonumber(n)
end
for _, v in ipairs(numbers) do
  io.write(v .. " ")
end
print()  -- 1 234.0 56.0 567.89 666.67

文字列位置の正規化

Luaの負のインデックスを使うと、文字列の末尾を基準に操作できます。string.sub(s, -n)は最後のn文字を取得します。#sと組み合わせて位置を計算することもできます。正のインデックスと負のインデックスの関係を理解すると、オフバイワンエラーを防げます。

local s = "abcdefgh"

-- Last 3 characters
print(s:sub(-3))     -- fgh

-- All but last 2
print(s:sub(1, -3))  -- abcdef

-- Character at position from end
print(s:sub(-1, -1)) -- h
print(s:sub(-4, -2)) -- efg

確認問題

string.sub("hello", 2, -2)は何を返しますか。

まとめ:検索と抽出

まとめ:

  • string.find(s, pat, init, plain) — 開始位置と終了位置、またはnilを返します
  • string.sub(s, i, j) — 位置を指定して抽出します。負のインデックスは末尾から数えます
  • string.match(s, pat) — キャプチャ、または一致した全体を返します
  • リテラル検索(マジック文字なし)にはplain=trueを使います
  • string.gmatchで分割処理を実装します
  • トリミングにはパターン"^%s*(.-)%s*$"を使います

よくある質問

「部分文字列の検索と抽出」レッスンは無料ですか?

はい。「部分文字列の検索と抽出」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Lua Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Lua Academyコースには全4レッスンが含まれています。

「部分文字列の検索と抽出」で何を学びますか?

string.findとstring.subを使ってテキストを検索・抽出します。 ブラウザで直接実行するハンズオンコードでLua Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

Lua Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのLua Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン2/4です。

「部分文字列の検索と抽出」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このLua Academyレッスンでコードを書いて実行できますか?

はい。すべてのLua Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. 文字列の基礎:連結と長さ
  2. 部分文字列の検索と抽出
  3. 出力のためのstring.format
  4. string.gsubとstring.gmatch
← Lua Academyに戻る