Сначала поговорим о том, почему ваш код не работает.
Во-первых, в ваших шаблонах есть обратная косая черта, поэтому без обратной косой черты вы ничего не пропустите:
print(t) -- test\([%w_]+)
print(n) -- test\([%a%d]+)([%;%,%.%s]?)
Но есть и другая проблема. Единственная вещь с обратной косой чертой, которая должна совпадать в вашем тестовом сообщении, это TEST\admin. Но здесь TEST все в верхнем регистре, а сопоставление с образцом чувствительно к регистру, поэтому вы его не найдете.
Таким образом, первая часть ответа заключается в создании шаблона без учета регистра. Это можно сделать следующим образом:
s= "[Tt][Ee][Ss][Tt]"
Здесь я заменил каждую букву классом символов, который будет соответствовать либо прописной, либо строчной букве.
Но что произойдет, если мы поищем этот шаблон в исходном сообщении? У нас будет досадная проблема: мы найдем тестирование и ИСПЫТАНИЕ. Похоже, вы уже сталкивались с этой проблемой, когда писали "([%;%,%.%s]?)".
Лучший способ сделать это - шаблон границы. (Обратите внимание, что шаблон границы — это недокументированная функция в Lua 5.1. Я не уверен, есть ли она в Lua 5.0 или нет. Она стала задокументированной функцией в Lua 5.2.)
Шаблон границы принимает набор символов и будет сопоставлять только пробелы между символами, где предыдущий символ не находится в наборе, а следующий символ находится в наборе. Это звучит сложно, но в основном это позволяет вам находить начало или окончание слов.
Чтобы использовать шаблон границы, нам нужно выяснить, как может выглядеть домен или имя пользователя. Возможно, мы не сможем сделать это идеально, но на практике чрезмерная жадность должна быть приемлемой.
s = "%f[%w-][Tt][Ee][Ss][Tt]%f[^%w-]"
Этот новый шаблон будет соответствовать "TEST" и "test", но не будет соответствовать "TESTING" или "testing".
Прежде чем продолжить, давайте рассмотрим проблему, которая может возникнуть с таким доменом, как ваш «рабочий пользователь». Символ "-" имеет особое значение в шаблонах, поэтому мы должны избегать его. Все специальные символы можно экранировать, добавив перед ними «%». Итак, наш шаблон рабочего пользователя будет выглядеть так:
s = "%f[%w-][Ww][Oo][Rr][Kk]%-[Uu][Ss][Ee][Rr]%f[^%w-]"
Что ж, такие шаблоны ужасно писать, поэтому давайте попробуем написать функцию, которая сделает это за нас:
function string_to_pattern(str, frontier_set, ci)
-- escape magic characters
str = str:gsub("[][^$()%%.*+-?]", "%%%0")
if ci then
-- make the resulting pattern case-insensitive
str = str:gsub("%a", function(letter)
return "["..letter:upper()..letter:lower().."]"
end)
end
if frontier_set then
str = "%f["..frontier_set.."]"..str.."%f[^"..frontier_set.."]"
end
return str
end
print(string_to_pattern("work-user", "%w-", true))
-- %f[%w-][Ww][Oo][Rr][Kk]%-[Uu][Ss][Ee][Rr]%f[^%w-]
Теперь я упомяну крайний случай: этот шаблон не будет соответствовать «-work-user» или «work-user-». Это может быть хорошо или нет, в зависимости от того, какие сообщения генерируются. Вы можете взять «-» из граничного набора, но тогда вы совпадете, например. "моя-работа-пользователь". Вы можете решить, имеет ли это значение, но я не думал, как это решить с помощью языка сопоставления с образцом Lua.
Теперь, как нам заменить совпадение на *? Эта часть довольно проста. Встроенная функция string.gsub позволит нам заменить совпадения наших шаблонов другими строками. Нам просто нужно сгенерировать замещающую строку, состоящую из знаков * и символов.
function string_to_stars(str)
return ("*"):rep(str:len())
end
local pattern = string_to_pattern("test", "%w-", true)
print( (test_string:gsub(pattern, string_to_stars)) )
Теперь последняя проблема. Мы можем сопоставлять пользователей в тех же доменах, что и мы. Например:
-- note that different frontier_set here
-- I don't know what the parameters for your usernames are,
-- but this matches your code
local pattern = string_to_pattern("admin", "%w_", true)
print( (test_string:gsub(pattern, string_to_stars)) )
Однако, даже если мы заменим все домены и имена пользователей по отдельности, обратная косая черта между «TEST» и «admin» в «TEST\admin» не заменится. Мы могли бы сделать такой хак:
test_string:gsub("%*\\%*","***")
Это заменит «**» на «***» в окончательном выводе. Однако это не совсем надежно, потому что может заменить «**», который был в исходном сообщении, а не в результате нашей обработки. Чтобы сделать все правильно, нам пришлось бы перебрать все пары домен+пользователь и сделать что-то вроде этого:
test_string:gsub(domain_pattern .. "\\" .. user_pattern, string_to_stars)
Обратите внимание, что это необходимо сделать перед любой другой заменой, так как в противном случае домен и имя пользователя уже будут заменены и больше не могут сопоставляться.
Теперь, когда проблема решена таким образом, позвольте мне предложить альтернативный подход, который больше похож на то, что я написал бы с нуля. Я думаю, что это, вероятно, проще и читабельнее. Вместо того, чтобы использовать сопоставление с образцом для точного поиска наших доменов и имен пользователей, давайте просто сопоставим токены, которые могут быть доменами или именами пользователей, а затем проверим, точно ли они совпадают, позже.
local message = -- broken into multiple lines only for
-- formatting reasons
"User tried to login from TEST\\admin; but should "
.."have logged in from work-user\\user1, No logs present "
.."for testing\\guest, account. The domain test.com and "
.."WORK-USER.org are active and TESTING domain in inactive"
-- too greedy, but may not matter in your case
local domain_pattern = "%w[%w-]*"
-- again, not sure
local user_pattern = "[%w_]+"
-- for case-insensitivity, call :lower before inserting into the set
local domains = {["test"]=true, ["work-user"]=true}
local users = {["admin"]=true, ["guest"]=true}
local pattern = "(("..domain_pattern..")\\("..user_pattern.."))"
message = message:gsub(pattern, function(whole, domain, user)
-- only call lower if case-insensitive
if domains[domain:lower()] and users[user:lower()] then
return string_to_stars(whole)
else
return whole
end
end)
local function replace_set(message, pattern, set, ci)
return (message:gsub(pattern, function(str)
if ci then str = str:lower() end
if set[str] then
return string_to_stars(str)
else
return str
end
end))
end
message = replace_set(message, domain_pattern, domains, true)
message = replace_set(message, user_pattern, users, true)
print(message)
Обратите внимание, насколько просты шаблоны в этом примере. Нам больше не нужны нечувствительные к регистру классы символов, такие как «[Tt]», потому что нечувствительность к регистру проверяется после сопоставления, заставляя обе строки быть строчными с помощью string.lower (что может быть не максимально эффективным, но, эй, это Луа). Нам больше не нужно использовать шаблон границы, потому что мы гарантированно получим полные слова из-за жадного сопоставления. Обратная косая черта по-прежнему странная, но я справился с ней таким же «надежным» способом, как я предложил выше.
Последнее замечание: я точно не знаю, почему вы это делаете, но я могу предположить, что это делается для того, чтобы кто-то не мог видеть домены или имена пользователей. Замена их на * не обязательно лучший способ. Во-первых, сопоставление таким образом может быть проблематичным, если ваши сообщения (например) разделены буквами. Это кажется маловероятным для удобных для пользователя сообщений, но я не знаю, стоит ли на это рассчитывать, когда на карту поставлена безопасность. Другое дело, что вы не скрываете длины доменов или имен пользователей. Это также может быть основным источником неуверенности. Например, пользователь может обоснованно предположить, что ***** — это «admin».
person
tehtmi
schedule
24.03.2015
test_string="User tried to login from TEST\\admin; but should have logged in from work-user\\user1, No logs present for testing\\guest, account. The domain test.com and WORK-USER.org are active and TESTING domain in inactive" s= "test" t=( string.gsub(s.."$DNname", "%$(%w+)", {DNname="\\([%w]+)"}) ) n=( string.gsub(s.."$DNname", "%$(%w+)", {DNname="\\([%a%d]+)([%;%,%.%s]?)"}) ) print (t) print(n) r=string.match(test_string,t) res=string.match(test_string,n) print(r) print(res)
Печатает ноль и не может сопоставить какой-либо шаблон - person Namitha   schedule 23.03.2015