Language
日本語
English

Caution

JavaScript is disabled in your browser.
This site uses JavaScript for features such as search.
For the best experience, please enable JavaScript before browsing this site.

  1. Home
  2. Lua Dictionary
  3. string.gsub() (Pattern Replacement)

string.gsub() (Pattern Replacement)

string.gsub() is a pattern-replacement function provided by Lua's string library. It searches a string for all positions matching a pattern and replaces them with a specified string, table, or function. Its distinctive feature is that it returns two values: the resulting string and the number of replacements made.

Syntax

-- Basic syntax of string.gsub
-- s     : target string
-- pat   : Lua pattern (similar to regular expressions)
-- repl  : replacement (string, table, or function)
-- n     : optional; maximum number of replacements (integer)
-- returns: replaced string, number of replacements (two values)

result, count = string.gsub(s, pat, repl)
result, count = string.gsub(s, pat, repl, n)

-- Method call style (when s is a string object)
result, count = s:gsub(pat, repl)
result, count = s:gsub(pat, repl, n)

Syntax Reference

Pattern / FormDescription
string.gsub(s, pat, repl)Replaces all occurrences of pattern pat in string s with repl.
string.gsub(s, pat, repl, n)Limits replacements to a maximum of n occurrences, processing from the start.
repl as stringReplaces matched portions with the literal string. %0 refers to the whole match; %1%9 refer to capture groups.
repl as tableUses the first capture (or the whole match if no captures) as a key to look up the table. The value is used as the replacement. If the value is false / nil, no replacement is made.
repl as functionCalls the function with the captures (or the whole match) as arguments for each occurrence. The return value is used as the replacement. If the return value is false / nil, no replacement is made.
%0Inside a repl string, refers to the entire matched portion.
%1%9Inside a repl string, refers to the contents of the corresponding capture group.
Return value (1st)The string after all replacements. The original string is not modified.
Return value (2nd)The number of replacements actually made (integer).

Sample Code

kiryu_gsub.lua
-- kiryu_gsub.lua — string.gsub() basics sample
-- Uses Yakuza (Like a Dragon) characters to demonstrate each replacement pattern

-- -----------------------------------------------
-- 1. repl as string
-- -----------------------------------------------

local line = "I am Kiryu Kazuma. They call me the Dragon of Dojima."

-- Replaces all occurrences of the pattern with a fixed string
local result1, count1 = string.gsub(line, "Kiryu Kazuma", "Majima Goro")
print("[repl = string]")
print("  Before: " .. line)
print("  After:  " .. result1)
print("  Count:  " .. count1)  -- 1
print("")

-- -----------------------------------------------
-- 2. %0 (whole match) and %1 (capture) references
-- -----------------------------------------------

local name = "Dojima Daigo"
-- Capture with (...), then reference with %1
local result2, count2 = string.gsub(name, "(Dojima)", "[%1]")
print("[%1 capture reference]")
print("  Before: " .. name)
print("  After:  " .. result2)  -- [Dojima] Daigo
print("  Count:  " .. count2)  -- 1
print("")

-- %0 refers to the entire match
local words = "Nishiki Nishiki Nishiki"
local result3, _ = string.gsub(words, "Nishiki", "[%0]")
print("[%0 whole match reference]")
print("  After: " .. result3)  -- [Nishiki] [Nishiki] [Nishiki]
print("")

-- -----------------------------------------------
-- 3. Limiting replacements with the n argument
-- -----------------------------------------------

local chant = "yakuza yakuza yakuza yakuza yakuza"
-- Replace only the first 2 occurrences
local result4, count4 = string.gsub(chant, "yakuza", "outlaw", 2)
print("[n=2 replacement limit]")
print("  After:  " .. result4)  -- outlaw outlaw yakuza yakuza yakuza
print("  Count:  " .. count4)  -- 2
print("")

-- -----------------------------------------------
-- 4. repl as table
-- -----------------------------------------------

-- Uses the capture as a key to look up the replacement
local alias = {
    ["Kiryu"]  = "Dragon of Dojima",
    ["Majima"] = "Mad Dog of Shimano",
    ["Saejima"] = "Tiger of Tojo",
}

local text = "Kiryu, Majima, and Saejima gathered."
-- Apply each name replacement in sequence
local result5 = text
result5, _ = string.gsub(result5, "Kiryu",   alias)
result5, _ = string.gsub(result5, "Majima",  alias)
result5, _ = string.gsub(result5, "Saejima", alias)
print("[repl = table (sequential replacement)]")
print("  Before: " .. text)
print("  After:  " .. result5)
-- Dragon of Dojima, Mad Dog of Shimano, and Tiger of Tojo gathered.
print("")

-- -----------------------------------------------
-- 5. repl as function
-- -----------------------------------------------

-- The function's return value becomes the replacement string
local members = "Kiryu Kazuma,Majima Goro,Nishikiyama Akira,Saejima Taiga"

-- Convert comma-separated names to a numbered list
local index = 0
local result6, count6 = string.gsub(members, "([^,]+)", function(name)
    index = index + 1
    return index .. "." .. name
end)
print("[repl = function (numbered list)]")
print("  After:  " .. result6)
-- 1.Kiryu Kazuma,2.Majima Goro,3.Nishikiyama Akira,4.Saejima Taiga
print("  Count:  " .. count6)  -- 4
print("")

-- -----------------------------------------------
-- 6. No replacement when function returns false/nil
-- -----------------------------------------------

local roster = "Kiryu Kazuma Daigo Majima Goro Nishikiyama"
-- Wrap only names with 5 or more ASCII characters in brackets
local result7, _ = string.gsub(roster, "(%S+)", function(w)
    if #w >= 5 then
        return "[" .. w .. "]"
    end
    -- returning nil leaves the match unchanged
end)
print("[no replacement when function returns nil]")
print("  After: " .. result7)
-- [Kiryu] [Kazuma] [Daigo] [Majima] [Nishikiyama]
print("")
lua kiryu_gsub.lua
[repl = string]
  Before: I am Kiryu Kazuma. They call me the Dragon of Dojima.
  After:  I am Majima Goro. They call me the Dragon of Dojima.
  Count:  1

[%1 capture reference]
  Before: Dojima Daigo
  After:  [Dojima] Daigo
  Count:  1

[%0 whole match reference]
  After: [Nishiki] [Nishiki] [Nishiki]

[n=2 replacement limit]
  After:  outlaw outlaw yakuza yakuza yakuza
  Count:  2

[repl = table (sequential replacement)]
  Before: Kiryu, Majima, and Saejima gathered.
  After:  Dragon of Dojima, Mad Dog of Shimano, and Tiger of Tojo gathered.

[repl = function (numbered list)]
  After:  1.Kiryu Kazuma,2.Majima Goro,3.Nishikiyama Akira,4.Saejima Taiga
  Count:  4

[no replacement when function returns nil]
  After: [Kiryu] [Kazuma] [Daigo] [Majima] [Nishikiyama]

Common Mistakes

Forgetting the %0/%1 capture reference in the replacement string

The replacement string (third argument) supports capture references %1%9 and %0 for the entire match. Without knowing this, developers tend to implement this logic using a function instead, which is more verbose.

-- NG: implementing with a function when a capture reference would suffice (verbose)
local text = "Kiryu Kazuma and Majima Goro"
local result = string.gsub(text, "(Kiryu Kazuma)", function(m)
    return "[" .. m .. "]"
end)
print(result)  -- [Kiryu Kazuma] and Majima Goro
-- OK: use %1 in the replacement string to avoid the function
local text = "Kiryu Kazuma and Majima Goro"
local result = string.gsub(text, "(Kiryu Kazuma)", "[%1]")
print(result)  -- [Kiryu Kazuma] and Majima Goro

Forgetting to escape % in the replacement string

In the replacement string, % is the start of a capture reference. To output a literal %, write %%.

-- NG: a bare % in the replacement string causes an error or unexpected behavior
local text = "completion: 100"
-- local result = string.gsub(text, "%d+", "%")  -- error
-- OK: use %% to output a literal percent sign
local text = "completion: 100"
local result = string.gsub(text, "%d+", "100%%")
print(result)  -- completion: 100%

Forgetting the two return values and receiving only one

string.gsub returns two values: the resulting string and the replacement count. Receiving just one variable silently discards the count, which is fine in most cases. However, passing the return value directly to another function sends both values, which can cause unintended behavior.

-- NG: passing gsub's return value directly to print also outputs the count
local text = "Nishiki Nishiki Nishiki"
print(string.gsub(text, "Nishiki", "Kiryu"))  -- "Kiryu Kiryu Kiryu" and "3" both printed
-- OK: assign to variables first, then use them
local text = "Nishiki Nishiki Nishiki"
local result, count = string.gsub(text, "Nishiki", "Kiryu")
print(result)   -- "Kiryu Kiryu Kiryu"
print(count)    -- 3

Overview

string.gsub() is the most commonly used pattern-replacement function in Lua. Passing a string as the third argument repl performs a straightforward global replacement; passing a table enables dictionary-lookup replacement keyed by captures; passing a function enables dynamic, per-match replacement. When a function or value returns false or nil, that match is left unchanged. The fourth argument n limits the number of replacements, processing only the first n occurrences and ignoring the rest. The return value is always a pair of "resulting string" and "replacement count", so if only the count is needed, write local _, count = string.gsub(...). Within the replacement string, %0%9 are used for capture references, and a literal % must be written as %%. Related functions include string.find(), which returns only the first match position, and string.gmatch(), which iterates over matches.

If you find any errors or copyright issues, please .