Lua: условное разбиение строки с использованием gmatch
Я пишу плагин для Mushclient в Lua. Mushclient включает в себя мод PCRE, который позволяет мне компилировать регулярные выражения с помощью функции rex.new. Я не уверен, нужно ли мне использовать это, чтобы выполнить то, что я пытаюсь сделать, но я подозреваю, что могу, хотя я бы предпочел этого не делать.
По сути, я хотел бы иметь возможность разбить строку на таблицу, используя разделители "," или "и". Однако в некоторых случаях эти "разделители" появляются внутри элемента, который я хотел бы оставить неразделенным (например, Феликс, Кот). Вот что я сделал до сих пор:
false_separators = {"Felix, the Cat", "orange and tan cat", "black and white cat"}
separators = rex.new(" ?(.+?)(?:,| and )")
local sample_text = "a black and white cat, a tabby cat, a giant cat, Felix, the Cat and an orange and tan cat."
index = 1
matches = {}
separators:gmatch(sample_text, function (m, t)
for k, v in pairs(t) do
print(v)
table.insert(matches, v)
end
end)
Это выведет:
a black
white cat
a tabby cat
a giant cat
Felix
the Cat
an orange
Есть две проблемы с этим. Во-первых, последний пункт не включен. Во-вторых, я не понял, как реализовать мою таблицу false_separators. Мой желаемый результат:
a black and white cat
a tabby cat
a giant cat
Felix, the Cat
an orange and tan cat
Я мог бы сделать это с большим количеством gsubing, но это кажется не элегантным и возможно эксплуатируемым или медленным:
false_separators = {"Felix, the Cat", "orange and tan cat", "black and white cat"}
local sample_text = "a black and white cat, a tabby cat, a giant cat, Felix, the Cat and an orange and tan cat."
function split_cats(text, false_sep)
for k, v in ipairs(false_sep) do
text = text:gsub(v, v:gsub(" ", "_")) -- replace spaces in false separator matches with underscores
end
text = text:gsub(" and ", ", "):gsub(", ", ";") -- replace ' and ' (that isn't surrounded by underscores) with a comma, then replace all commas that aren't followed by underscores with a semi-colon. Semi-colon is now the true delimiter
m = utils.split (text, ";") or {} -- split at semi-colon
for i, v in ipairs(m) do
m[i] = v:gsub("_", " ") -- remove underscores
end
return m
end
table.foreach(split_cats(sample_text, false_separators), print)
Выход:
1 a black and white cat
2 a tabby cat
3 a giant cat
4 Felix, the Cat
5 an orange and tan cat.