Is it possible to substitute characters according to a list in Lua, like tr
in Perl? For example, I would like to substitute A
to B
and B
to A
(e.g. AABBCC
becomes BBAACC
).
In Perl, the solution would be $str ~= tr/AB/BA/
. Is there any native way of doing this in Lua? If not, I think the best solution would be iterating through the entire string, since separate substitutions need to use a special symbol to distinguish characters that were already substituted and characters that weren't.
Edit: my goal was to calculate the reverse complement of a DNA string, as described here.
gsub (s, pattern, repl [, n]) Returns a copy of s in which all (or the first n , if given) occurrences of the pattern have been replaced by a replacement string specified by repl , which can be a string, a table, or a function. gsub also returns, as its second value, the total number of matches that occurred.
According to the documentation, %s means whitespace, and %S means anything other than whitespace. So that match expression will split on one or more whitespace characters, capturing the two strings on either side.
The easiest way is to use the built-in substring() method of the String class. In order to remove the last character of a given String, we have to use two parameters: 0 as the starting index, and the index of the penultimate character.
string.gsub
can take a table as the third argument. The table is queried for each match, using the first capture as the key, and the associated value is used as the replacement string. If the value is nil
, the match is not changed.
So you can build a helper table like this:
local s = "AABBCC"
local t = {A = "B", B = "A"}
local result = string.gsub(s, "[AB]", t)
print(result)
or this same one-liner:
print((string.gsub("AABBCC", "[AB]", {A = "B", B = "A"})))
Output:
BBAACC
For a one character pattern like "[AB]"
, "."
can work as well because whatever not found in the table won't be changed. (But I don't think that's more efficient) But for some more complicated cases, a good pattern is needed.
Here is an example from Programming in Lua: this function substitutes the value of the global variable varname
for every occurrence of $varname
in a string:
function expand (s)
return (string.gsub(s, "$(%w+)", _G))
end
The code below will replace each character with a desired mapping (or leave alone if no mapping exists). You could modify the second parameter to string.gsub
in tr
to be more specific if you know the exact range of characters.
s = "AABBCC"
mappings = {["A"]="B",["B"]="A"}
function tr(s,mappings)
return string.gsub(s,
"(.)",
function(m)
-- print("found",m,"replace with",mappings[m],mappings[m] or m)
if mappings[m] == nil then return m else return mappings[m] end
end
)
end
print(tr(s,mappings))
Outputs
henry@henry-pc:~/Desktop$ lua replace.lua
found A replace with B B
found A replace with B B
found B replace with A A
found B replace with A A
found C replace with nil C
found C replace with nil C
BBAACC 6
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With