--過濾敏感詞(如果onlyKnowHas為true,表示只想知道是否存在敏感詞,不會返回過濾后的敏感詞,比如用戶注冊的時候,我們程序是只想知道用戶取的姓名是否包含敏感詞的(這樣也能提高效率,檢測到有一個敏感詞就直接返回),而聊天模塊是要返回過濾之后的內容的,那么onlyKnowHas可以不設,但這需要遍歷所有可能) local function filterSensitiveWords( content , onlyKnowHas) if content == nil or content == '' then return '' end --獲取每一個字符 local wordlist = {} local q = 1 for w in string.gmatch(content, ".[\128-\191]*") do wordlist[q]= w q=q+1 end --獲取字符串中從起始位置到結束位置的字符 local function findWord( wordTable, startpos,endpos ) local result = '' for i=startpos,endpos do result = result..wordTable[i] end return result end local length = #(string.gsub(content, "[\128-\191]", "")) --計算字符串的字符數(而不是字節數) local i,j = 1,1 local replaceList={} local mgc = {['敏感詞1']=true,['敏感詞2']=true,['敏感詞3']=true} local function check( ) local v = findWord(wordlist,i,j) local item = mgc[v] if item == true then if onlyKnowHas == true then return true end table.insert(replaceList,v) j = j+1 i = j else j = j+1 end local limit = (j-i) >= 15 and true or (j > length and true or false) if limit == true then --因為一個敏感詞最多15個字,不會太長,目的提高效率 i = i +1 j = i end if i <= length then check() end end check() if onlyKnowHas == true then return false end --模式串中的特殊字符 ( ) . % + - * ? [ ^ $ -- % 用作特殊字符的轉義字符,比如%%匹配字符% %[匹配字符[ local specialChar = {['(']=true,[')']=true,['.']=true,['%']=true,['+']=true,['-']=true,['*']=true,['?']=true,['[']=true,['^']=true,['$']=true} --檢測是否有特殊字符 local function checkSpecialChar( msg ) local tArray = string.gmatch(msg, ".[\128-\191]*") local contentArray = {} for w in tArray do table.insert(contentArray,w) end local ck = {} for i=1,#contentArray do local v = contentArray[i] if specialChar[v] == true then table.insert(ck,'%') end table.insert(ck,v) end local result='' for i,v in ipairs(ck) do result = result..v end return result end for i,v in ipairs(replaceList) do -- --這里我沒用,主要還是為了效率 -- local count = #(string.gsub(content, "[\128-\191]", "")) --判斷多少個字符(用於計算要顯示的*個數) -- local star = '' -- for i=1,count do -- star = star..'*' -- end v = checkSpecialChar(v) content = string.gsub( content , v , '***' ) end return content end
目前認為最優算法如下:
local function filterSensitiveWords( content , onlyKnowHas) if content == nil or content == '' then return '' end --模式串中的特殊字符 ( ) . % + - * ? [ ^ $ -- % 用作特殊字符的轉義字符,比如%%匹配字符% %[匹配字符[ local specialChar = {['(']=true,[')']=true,['.']=true,['%']=true,['+']=true,['-']=true,['*']=true,['?']=true,['[']=true,['^']=true,['$']=true} --檢測是否有特殊字符 local function checkSpecialChar( msg ) local tArray = string.gmatch(msg, ".[\128-\191]*") local contentArray = {} for w in tArray do table.insert(contentArray,w) end local ck = {} for i=1,#contentArray do local v = contentArray[i] if specialChar[v] == true then table.insert(ck,'%') end table.insert(ck,v) end local result='' for i,v in ipairs(ck) do result = result..v end return result end --因為找不到方案禁用虛擬鍵盤的回車鍵,所以只能代碼移除回車鍵(游戲中虛擬鍵盤不應有換行鍵的) --如果可以使用回車鍵的話,那么就可以發布豎着的敏感詞文字了,顯示的很明顯,沒有閱讀障礙,但明文規定不能出現很明顯的敏感詞 --用字符隔開的敏感詞是可以接受的,因為這種用字符隔開的敏感詞情況太多,根本無法避免,所以是可以接受的 --InputField有一個枚舉類型keyboardType來設置鍵盤的,具體沒試,也許也是一種解決方案 local tempContent = '' for w in contentArray do if string.byte(w) ~= 10 then --表示回車(換行) tempContent = tempContent..w end end content = tempContent contentArray = string.gmatch(tempContent, ".[\128-\191]*") local mgc = {'敏'={'敏1','敏2','敏3'},,'黨'={'黨1'}} local contentArray = string.gmatch(content, ".[\128-\191]*") local value,startpos,endpos,length,star local starChar ='*' --循環每一個字符 for w in contentArray do value = mgc[w] if w ~= starChar and value ~= nil then for i,v in ipairs(value) do local z = checkSpecialChar(v) startpos,endpos = content:find(z) if startpos ~= nil and endpos ~= nil then if onlyKnowHas == true then return true end length = #(string.gsub(v, "[\128-\191]", "")) star = '' for i=1,length do star = star..starChar end content = string.gsub( content , z , star ) break end end end end if onlyKnowHas == true then return false end return content end