lua中中文单词前一个可选空格的正则表达式

问题描述 投票:0回答:1

我尝试使用

string.match("Í",'%s?[\u{4e00}-\u{9FFF}]+')
,这与我们在 JS 或其他语言中的工作方式类似。但它会匹配一个不必要的字符,如上面的“Í”。

匹配UTF-8官方实现是使用eacape

\ddd
但是
\u{XXX}
似乎失败了因为

Lua 的模式匹配设施按字节工作

暂时,我使用类似于

utf8.charpattern
的不稳定解决方法:
string.match("Í",'%s?[\228-\233][%z\1-\191][%z\1-\191]')
基于 utf8 编码 将输出
nil
并可用于检查 cjk(如“我”),尽管它对于左侧第二个字节有一个错误的范围.

问:

如何用正则表达式解决这个问题?

unicode lua cjk lua-patterns
1个回答
0
投票
  1. Lua 模式不是正则表达式。正则表达式具有 Lua 模式所没有的功能(例如分组、可能嵌套和选择),并且 Lua 模式具有正则表达式(至少在形式语言意义上)所没有的功能(例如
    %b
    %1
    )。
  2. 你是对的:Lua 模式不是在“代码点”上操作,而是在字节上操作。这就是为什么
    \u{4e00}-\u{9FFF}
    不起作用:Lua在这里看到的是
    \228\184\128-\233\191\191
    ,相当于
    \184\191\228\128-\233
    ,这与你想要的有很大不同(值得注意的是,范围突然从
    \128
    \233
    )。我认为
    -
    与在源代码中显示为单个代码点的多字节“字符”的交互有点像枪炮。

由于您想要一个纯 Lua 解决方案,并且考虑到您的模式的简单性,因此手工解决方案是可行的:

local codepoints = {}
for _, c in utf8.codes(s) do
    if utf8.char(c):match"^%s$" and codepoints[1] == nil then
        codepoints[1] = c
    elseif c >= 0x4e00 and c <= 0x9FFF then
        table.insert(codepoints, c)
    else
        codepoints = {}
    end
end
local match = utf8.char(table.unpack(codepoints))
if match:match"^%s?$" then match = nil end -- single space or empty string
© www.soinside.com 2019 - 2024. All rights reserved.