Regex in Lua¶
Lua has its own support for regular expressions (). This gives another option aside from Vim's built-in regex support.
Table of Contents¶
string.match
¶
Usage¶
Using string.match
is the easiest way to extract text from a string with regex.
If the regex matches, string.match
returns the captures from the pattern,
otherwise it returns nil
.
If the regex doesn't have any capture groups, then the whole match is returned.
local captures = line:match('^(#+) (.+)')
local entire_match = line:match('^#+ .+')
nil
as a match, it can be useful for if
statements.
if line:match('^(#+)') then
local level = line:match('^(#+)')
local title = line:match('^#+ (.+)')
end
Get Multiple Captures from One Regex¶
Each capture group in the regex returns a string. To get multiple capture groups:
local line = vim.fn.getline('.')
local capture1, capture2 = line:match('^(#+) (.+)')
vim.print(("First capture: %s, Second capture: %s"):format(capture1, capture2))
Using gsub¶
See lua patterns.
Using gsub
is another way to use regex in Lua.
It accepts Lua "patterns."
gsub
Syntax¶
string.gsub({string}, {pattern_to_replace}, {replace_with} [, {n}])
The patterns use %
as the escape character instead of \
.
i.e., %1
- %9
for capture groups, and %0
for the entire match.
The replace_with
field can be a string, a table, or a function.
If you specify a function, it'll be called for each match.
If replace_with
is a string, then it is used as a replacement.
local text = "I love Lua!"
local newText = string.gsub(text, "Lua", "programming")
print(newText) -- Output: I love programming!
If replace_with
is a table, then gsub
queries the table with each
capture group, and when a matching key is found, it uses that as a replacement.
local text = "I love Lua and Python."
local replacements = { Lua = "Go", Python = "C" }
local newText = string.gsub(text, "(Lua) and (Python)", replacements)
print(newText) -- Output: I love Go and C.
If replace_with
is a function, then it is called with the capture groups.
This function is called every time a match occurs, and all captured
substrings are passed as arguments (in order).
local text = "3 chickens, 5 cows, and 2 ducks"
local newText = string.gsub(text, "%d+", function(n) return tonumber(n) * 2 end)
print(newText) -- Output: 6 chickens, 10 cows, and 4 ducks
Another example using a function:¶
x = string.gsub("4+5 = $return 4+5$", "%$(.-)%$", function (s)
return loadstring(s)()
end)
The pattern:
"%$(.-)%$"
%$
Matches literal dollar signs ($
)*
(.-)
is a non-greedy quantifier. This "lazy" matches as few characters as possible.
This pattern matches and captures any substring that starts
and ends with a $
character.
The match is then passed to the replacement function, which takes the captured substring as an argument.
-
The Replacement Function:
- Instead of a simple replacement string, a function is provided as the replacement argument.
- Lua calls this function for every match, passing the captured string
as the argument
s
. - In this case,
s
will receive the string"return 4+5"
from between the$
signs.
-
loadstring
Function:loadstring(s)
is a function that compiles a string containing Lua code into a Lua function.- In this context,
s
is"return 4+5"
. - Note: In Lua 5.2 and later,
loadstring
is replaced byload
. However, the behavior is similar.
-
Executing the Compiled Code:
- The
()
immediately followingloadstring(s)
invokes the compiled function. - Since
s
is"return 4+5"
, this compiled function, when called, evaluates the expression and returns9
.
- The
-
Final Outcome:
- The final value of
x
after executing this snippet is"4+5 = 9"
, and the embedded Lua code within$...$
is evaluated and replaced in the output string.