
Встречал на форумах уже готовые скрипты с решённой проблемой, но они довольно сложные, я там вообще ничего не понимаю. А когда много не понимаешь, чувствуешь себя некомфортно. Буду признателен, если поможете.
Код: Выделить всё
--[[
Возвращает итератор, который, при каждом вызове, возвращает индексы начала и
конца совпадения с шаблоном и захваченные значения (captures).
]]
function gfind_patterns(string_, patterns)
return coroutine.wrap(function ()
for _, pattern in ipairs(patterns) do
local i = 1
while true do
local results = {string_:find(pattern, i)}
if not results[1] then
break
end
i = results[2] + 1
coroutine.yield(unpack(results))
end
end
end)
end
--[[
"Поглощает" итератор и возвращает все полученные значения в виде массива.
]]
function collect_results(iterator)
local all_results = {}
while true do
local results = {iterator()}
if not results[1] then
break
end
table.insert(all_results, results)
end
return all_results
end
--[[
Возвращает true если сообщение содержит части совпадающие с forbidden_patterns и
не совпадающие с allowed_patterns, иначе возвращает false.
]]
function is_forbidden(message, forbidden_patterns, allowed_patterns)
local allowed_indexes = collect_results(gfind_patterns(message, allowed_patterns))
for start, end_ in gfind_patterns(message, forbidden_patterns) do
local forbid = true
for _, indexes in ipairs(allowed_indexes) do
if start >= indexes[1] and end_ <= indexes[2] then
forbid = false
break
end
end
if forbid then
return true
end
end
return false
end
--[[
Тесты.
]]
local forbidden_patterns = {'http://', 'www%.', '%d+%.%d+%.%d+%.%d+'}
local allowed_patterns = {'http://dchublist%.ru', 'www%.dchublist%.ru', '127%.0%.0%.1'}
for _, test in ipairs({
'http://spam.net',
'www.spam.net 127.0.0.1',
'http://dchublist.ru www.spam.net',
}) do
assert(is_forbidden(test, forbidden_patterns, allowed_patterns), 'failed: ' .. test)
end