gpt4 book ai didi

regex - 检测 Lua 中的最后一个字符是否不是多字节

转载 作者:行者123 更新时间:2023-12-04 21:53:07 25 4
gpt4 key购买 nike

第一个问题。 Lua 中确定字符串中的最后一个字符是否不是多字节的最简单方法是什么。或者从字符串中删除最后一个字符的最简单方法是什么。

以下是有效字符串的示例,以及我希望函数的输出是什么

hello there     --- result should be:   hello ther
anñ --- result should be: an
כראע --- result should be: כרא
ㅎㄹㅇㅇㅅ --- result should be: ㅎㄹㅇㅇ

我需要类似的东西
function lastCharacter(string)
--- some code which will extract the last character only ---
return lastChar
end

或者如果它更容易
function deleteLastCharacter(string)
--- some code which will output the string minus the last character ---
return newString
end

这是我要走的路
local function lastChar(string)
local stringLength = string.len(string)
local lastc = string.sub(string,stringLength,stringLength)
if lastc is a multibyte character then
local wordTable = {}
for word in string:gmatch("[\33-\127\192-\255]+[\128-\191]*") do
wordTable[#wordTable+1] = word
end
lastc = wordTable[#wordTable]
end
return lastc
end

最佳答案

首先注意Lua的string中没有函数了解 Unicode/多字节编码的库(来源:Lua 编程,第 3 版)。就 Lua 而言,字符串只是由字节组成。如果您使用的是 UTF-8 编码的字符串,则由您决定哪些字节构成一个字符。因此,string.len会给你字节数,而不是字符数。和 string.sub会给你一个字节子串而不是字符子串。

一些 UTF-8 基础知识:

如果您需要了解 Unicode 的基本概念,您应该查看 this article .

UTF-8 是 Unicode 的一种可能(且非常重要)的实现 - 并且可能是您正在处理的一种。与 UTF-32 和 UTF-16 不同,它使用可变字节数(从 1 到 4)对每个字符进行编码。特别是,ASCII 字符 0 到 127 用单个字节表示,因此可以使用 UTF-8 正确解释 ASCII 字符串(反之亦然,如果您只使用那 128 个字符)。所有其他字符都以 194 到 244 范围内的一个字节开头(这表示后面有更多字节来编码一个完整字符)。这个范围被进一步分割,这样你就可以从这个字节中看出后面是 1、2 还是 3 个字节。这些额外的字节称为连续字节,并且保证只取自 128 到 191 的范围。因此,通过查看单个字节,我们知道它在字符中的位置:

  • 如果在 [0,127] , 它是一个单字节 (ASCII) 字符
  • 如果在 [128,191] ,它是较长字符的一部分,本身毫无意义
  • 如果在 [191,244] ,它标志着一个较长字符的开始(并告诉我们该字符有多长)

  • 此信息足以计算字符数、将 UTF-8 字符串拆分为字符以及执行各种其他对 UTF-8 敏感的操作。

    一些模式匹配基础:

    对于手头的任务,我们需要一些 Lua 的模式匹配结构:
    [...]是一个字符类,它匹配类中的单个字符(或更确切地说是字节)。例如。 [abc]匹配 a , 或 bc .您可以使用连字符定义范围。因此 [\33-\127]例如,匹配来自 33 的任何单个字节至 127 .请注意 \127是一个可以在任何 Lua 字符串(不仅仅是模式)中使用的转义序列,以通过其数值而不是相应的 ASCII 字符来指定字节。例如, "a""\97" 相同.

    你可以否定一个字符类,以 ^ 开头。 (以便它匹配不属于该类的任何单个字节。
    *重复前一个标记 0 次或更多次(任意多次 - 尽可能频繁)。
    $是一个 anchor 。如果它是模式的最后一个字符,则模式将只匹配字符串的末尾。

    结合所有这些...

    ...您的问题简化为单行:
    local function lastChar(s)
    return string.match(s, "[^\128-\191][\128-\191]*$")
    end

    这将匹配不是 UTF-8 连续字符的字符(即,单字节字符或标记较长字符开头的字节)。然后它匹配任意数量的连续字符(由于选择的范围,这不能超过当前字符),然后是字符串的结尾( $ )。因此,这将为您提供构成字符串中最后一个字符的所有字节。它为您的所有 4 个示例生成所需的输出。

    同样,您可以使用 gsub从字符串中删除最后一个字符:
    function deleteLastCharacter(s)
    return string.gsub(s, "[^\128-\191][\128-\191]*$", "")
    end

    匹配是相同的,但我们没有返回匹配的子字符串,而是将其替换为 "" (即删除它)并返回修改后的字符串。

    关于regex - 检测 Lua 中的最后一个字符是否不是多字节,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15979519/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com