Lua中特殊字符过滤(UTF8编码)

Table of Contents

  1. 提纲
    1. 思路
    2. 中文Unicode
    3. Unicode和UTF8的联系
    4. 常见特殊字符
    5. 过滤特殊字符
  2. 思路
  3. 中文Unicode编码
  4. 根据字符的UTF8编码获取Unicode
  5. 需要过滤掉的特殊字符
  6. 代码实现

提纲

思路

中文Unicode

Unicode和UTF8的联系

常见特殊字符

过滤特殊字符

思路

常见的特殊字符有很多,查了很多资料,没找到特殊字符的Unicode编码范围,即使找到了也难以保证覆盖了全部。因此只能从非的角度考虑, 实现目标是留下操作系统支持的可作为文件名的字符。

中文Unicode编码

摘自https://www.qqxiuzi.cn/zh/hanzi-unicode-bianma.php





























































































字符集 字数 Unicode编码
基本汉字 20902字 4E00-9FA5
基本汉字补充 74字 9FA6-9FEF
扩展A 6582字 3400-4DB5
扩展B 42711字 20000-2A6D6
扩展C 4149字 2A700-2B734
扩展D 222字 2B740-2B81D
扩展E 5762字 2B820-2CEA1
扩展F 7473字 2CEB0-2EBE0
康熙部首 214字 2F00-2FD5
部首扩展 115字 2E80-2EF3
兼容汉字 477字 F900-FAD9
兼容扩展 542字 2F800-2FA1D
PUA(GBK)部件 81字 E815-E86F
部件扩展 452字 E400-E5E8
PUA增补 207字 E600-E6CF
汉字笔画 36字 31C0-31E3
汉字结构 12字 2FF0-2FFB
汉语注音 43字 3105-312F
注音扩展 22字 31A0-31BA
1字 3007

其中只需要考虑基本汉字字符集即可。

根据字符的UTF8编码获取Unicode

UTF8和Unicode的关系网上资料很多, 在此不再赘述,简而言之,中文的UTF8编码都是三个字节,1110xxxx 10xxxxxx 10xxxxxx, 剩余的16位正好放下Unicode编码的两个字节,因此只要取出这16位即可知道该字符的Unicode

Lua不支持位操作, b1 % 0xe0 代表 b1 & 0xe0,*212代表左移12位,依次类推

local b1 = string.byte(str, curIndex)
local b2 = string.byte(str, curIndex + 1)
local b3 = string.byte(str, curIndex + 2)
local unic = (b1 % 0xe0) * 2 ^ 12 + (b2 % 0x80) * 2 ^ 6 + (b3 % 0x80);

需要过滤掉的特殊字符

  1. ASCII中Windows不支持作为文件名的字符正则: [\\\\/:*?\"<>|%s+ ]
  2. 两个字节的UTF
  3. UTF编码在四个字节及四个字节以上的字符

可以使用此页面内的特殊字符进行测试: https://wenku.baidu.com/view/fddf6408844769eae009ed14.html?re=view

代码实现

-- 过滤中文特殊字符
function filterInvalidChars(str)
  local result = '';
  local curIndex = 1;
  -- 逐字检查, 符合要求则放入result
  repeat
    local curByte = string.byte(str, curIndex)
    if curByte > 0 and curByte <= 127 then
      result = result..string.sub(str, curIndex, curIndex)
      curIndex = curIndex + 1
    elseif curByte >= 192 and curByte <= 223 then
      curIndex = curIndex + 2
    elseif curByte >= 224 and curByte <= 239 then
      -- 此处判断一些中文特殊字符
      local b1 = curByte
      local b2 = string.byte(str, curIndex + 1)
      local b3 = string.byte(str, curIndex + 2)
      local unic = (b1 % 0xe0) * 2 ^ 12 + (b2 % 0x80) * 2 ^ 6 + (b3 % 0x80)
      if unic >= 0x4e00 and unic <= 0x9FA5 then
        result = result..string.sub(str, curIndex, curIndex + 2)
      end
      curIndex = curIndex + 3
    elseif curByte >= 240 and curByte <= 247 then
      curIndex = curIndex + 4
    else
      logger:error('filter invalid chars error: '..str)
      return str
    end
  until(curIndex >= #str);
  return string.gsub(result, '[\\\\/:*?\"<>|%s+ ]', '');
end

你可能感兴趣的:(Lua中特殊字符过滤(UTF8编码))