Lua 字符串魔法

本教程介绍了 Lua 字符串操作和解析技术,这些技术在多种应用程序中都非常有用,尤其是在需要检查和确认文本格式是否正确的商业或数据库驱动的应用程序中。

分割字符串

如果您有一些数据是以长字符串的形式存在,并且需要根据自定义模式将其分解成较小的字符串,该怎么办?一个常见的例子是街道地址

Flintstone, Fred, 101 Rockledge, Bedrock, 98775, 555-555-1212
Rubble, Barney, 103 Rockledge, Bedrock, 98775, 555-555-1313

现在,假设您要解析以逗号分隔的每段数据。Lua 的字符串库本身没有“分割”函数,但是使用一个小型函数,您可以实现相同的功能。查看以下代码

function string:split( inSplitPattern )

    local outResults = {}
    local theStart = 1
    local theSplitStart, theSplitEnd = string.find( self, inSplitPattern, theStart )

    while theSplitStart do
        table.insert( outResults, string.sub( self, theStart, theSplitStart-1 ) )
        theStart = theSplitEnd + 1
        theSplitStart, theSplitEnd = string.find( self, inSplitPattern, theStart )
    end

    table.insert( outResults, string.sub( self, theStart ) )
    return outResults
end

此函数可以优雅地完成所需的任务,提供一个用户定义的模式进行分割,并返回一个包含分割元素的表。

可以通过两种方式调用该函数,结果相同

local myString = "Flintstone, Fred, 101 Rockledge, Bedrock, 98775, 555-555-1212"

local myTable = myString:split( ", " )

for i = 1,#myTable do
    print( myTable[i] )
end
local myString = "Flintstone, Fred, 101 Rockledge, Bedrock, 98775, 555-555-1212"

local myTable = string.split( myString, ", " )

for i = 1,#myTable do
    print( myTable[i] )
end

修剪字符串

在很多情况下,修剪字符串都非常有用,尤其是在处理来自外部源的数据或用户通过设备键盘输入的数据时。与“分割”功能一样,字符串修剪不是 Lua 字符串库的原生功能,但可以轻松实现。查看以下函数

local function trimString( s )

    return string.match( s, "^()%s*$" ) and "" or string.match( s, "^%s*(.*%S)" )
end

使用它非常简单,只需将未修剪的字符串作为唯一参数传递即可

local trimmedString = trimString( "   Some untrimmed string here.     " )

print( "[" .. trimmedString .. "]" )  --> [Some untrimmed string here.]

格式化为标题大小写

有时,将字符串转换为“标题大小写”非常有用,其中每个单词的首字母转换为大写,而其余字母设置为小写。例如,假设一个名称以非常草率的格式输入,例如

Obi-waN kEnObi

当然,您可能想要更正它,而这样做只需要一个简单的函数

local function titleCase( s )

    local result = string.gsub( s, "(%a)([%w_']*)",
        function( first, rest )
            return first:upper() .. rest:lower()
        end
    )
    return result
end

如果将未格式化的字符串作为唯一参数传递给此函数,则结果与预期完全一致Obi-Wan Kenobi (欧比旺·克诺比).

local characterName = titleCase( "Obi-waN kEnObi" )

print( characterName )  --> Obi-Wan Kenobi

严格的换行

有时,您会有一长串(段落)文本需要在特定字符间隔处换行而不是像素距离处换行。如果您提供 `width` 参数,Corona 的 display.newText() API 会处理换行,但如果您想要特定间隔的控制,您可能更喜欢以下函数,它允许您将每行的最大字符数设置为 `limit` 参数。此外,它还允许您设置缩进值(作为可选字符串,而不是整数),用于段落的开头和/或后面的每一行。

local function textWrap( str, limit, indent, indentFirst )

    limit = limit or 72
    indent = indent or ""
    indentFirst = indentFirst or indent

    local here = 1 - #indentFirst
    return indentFirst .. str:gsub( "(%s+)()(%S+)()",
        function( sp, st, word, fi )
            if fi - here > limit then
                here = st - #indent
                return "\n" .. indent .. word
            end
        end
    )
end

让我们按顺序检查函数参数

textWrap( str, limit, indent, indentFirst )

`indentFirst`(可选的 字符串)— 仅第一行的缩进字符串。

local initialText = "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet."

local wrappedText = textWrap( initialText, 36, nil, "    " )

print( wrappedText )
    Lorem ipsum dolor sit amet,
consetetur sadipscing elitr, sed
diam nonumy eirmod tempor invidunt
ut labore et dolore magna aliquyam
erat, sed diam voluptua. At vero eos
et accusam et justo duo dolores et
ea rebum. Stet clita kasd gubergren,
no sea takimata sanctus est Lorem
ipsum dolor sit amet.

确认电子邮件格式

考虑到这一点,我们可以像这样调用函数并获得以下输出

local function confirmEmail( s )

    if ( s:match("[A-Za-z0-9%.%%%+%-]+@[A-Za-z0-9%.%%%+%-]+%.%w%w%w?%w?") ) then
        return true
    else
        return false
    end
end

另一个有用的字符串检查是确认用户输入的电子邮件地址格式正确。当然,此函数无法检查实际地址是否有效且可用,但至少可以确认格式基本正确。

local isEmailFormat = confirmEmail( "[email protected]" )

print( isEmailFormat )  --> true

去除表情符号

如果将电子邮件地址作为唯一参数传递,您可以看到该函数只返回一个布尔值 `true` 或 `false`,具体取决于电子邮件地址的格式是否正确。

表情符号或“emoji”是视觉符号,人们可以通过文本轻松表达想法或感受。不幸的是,如果您需要将包含表情符号的字符串保存到 SQLite 数据库、使用 JSON 编码/解码字符串等,这些字符可能会造成严重破坏。如果您的应用程序接受用户文本输入(自定义玩家姓名等)

local function stripNonStandardCharacters( s )

    local res = ""
    for i = 1, utf8.len(s) do
        local c = utf8.sub( s, i, i )
        if utf8.codepoint( c ) <= 65535 then
            res = res .. c
        end
    end
    return res
end

其中玩家可能包含表情符号,但您需要将它们去除以进行数据存储/转换,则以下函数可以完成此任务请注意,此函数需要使用免费的 Corona UTF-8 插件,因此您需要将其包含在您的项目中,并在包含此去除表情符号

总结

函数的模块中 `require()` 它。有关详细信息,请参阅插件文档