string - 以符合现有代码期望的方式迭代可能的空行

标签 string iterator lua pattern-matching

我曾经使用简单的方法迭代字符串中的行

for line in s:gmatch("[^\r\n]+") do

效果非常好!然后现实生活发生了......

...现在我的要求发生了变化:我也需要匹配空行。问题是:由于这种形式的迭代在多个位置使用,而这些位置本身就是丛林,所以我想尽可能避免更改周围的代码。到目前为止,我对 gmatch/find 的尝试还无法为上述模式创建“直接”替换,因为上述函数无法实现的微妙期望来匹配。

我寻求的构造(for line in some_matcher(s) do)符合以下要求,我相信这些要求涵盖了我担心的所有边缘情况:

   INPUT            EXPECTATIONS

1. ''            -- match once   ('')
2. '\r\n'        -- match twice  ('', '')
3. '\r\n\r\n'    -- match thrice ('', '', '')
4. 'aaa'         -- match once   ('aaa')
5. 'aaa\r\n'     -- match twice  ('aaa', '')
6. 'aaa\r\nbbb'  -- match twice  ('aaa', 'bbb')
7. '\r\nbbb'     -- match twice  ('', 'bbb')

我的旧解决方案假设仅发生 \r\n 行结尾,如果新解决方案仅处理该场景,则完全没问题。

但是,由于我的商店正在谈论 Linux 支持计划,因此非常感谢并保存一个也处理更简单的 \n 行结尾(为了将来的 unix 兼容性)的答案几个月后重新审视这个问题。然而,问题是,在许多情况下,我需要原始字符串输入中的此匹配的起始列。如果上面的构造(for ... do)可以输出它作为一个额外的好处,那就特别棒了。

最佳答案

如果您需要以跨平台方式准确检测换行符边界而不是跳过/丢弃它们,则不能使用同时包含 \r\n,因为它将匹配换行符序列 \r\n 两次而不是一次(CRLF 在 DOS/Windows 上是单个换行符)。您可以使用足够强大的正则表达式引擎(例如支持交替)来处理这个问题,但 Lua 的模式匹配库非常少。

最好的选择是在处理文本之前规范换行符,如下所示:

function normalize_eols(s)
    return s
        :gsub('\r\n','\n')
        :gsub('\r', '\n')
end

对于您的输入=>输出网格,如果我们将换行符视为行分隔符,那么我期望[^\n]*(零或更多非换行符)可以工作,但我们得到以下结果:

''         => ('')
'\n'       => ('', '')
'\n\n'     => ('', '', '')
'aaa'      => ('aaa', '')
'aaa\n'    => ('aaa', '', '')
'aaa\nbbb' => ('aaa', '', 'bbb', '')
'\nbbb'    => ('', 'bbb', '')

老实说,我不知道为什么。

但是,如果我们将换行符视为行终止符,那么我们可以通过将换行符附加到输入并使用模式 [^\n] 来获得您想要的结果*\n(零个或多个非换行符,后跟换行符):

'\n'         => ('')
'\n\n'       => ('', '')
'\n\n\n'     => ('', '', '')
'aaa\n'      => ('aaa')
'aaa\n\n'    => ('aaa', '')
'aaa\nbbb\n' => ('aaa', 'bbb')
'\nbbb\n'    => ('', 'bbb')

所以你的代码将更改为:

s = normalize_eols(s) .. '\n'
for line in s:gmatch('([^\n]*)\n') do
    ...

关于string - 以符合现有代码期望的方式迭代可能的空行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10416869/

相关文章:

c++ - 标准容器的迭代器是 DefaultConstructible 吗?

scala - 为什么使用 scala 的迭代器实现 crossProduct 会返回错误的结果?

luarocks lyaml 安装错误

jQuery 中的 PHP 连接 $i

java - Struts2 中 getContextMap() 和 getValueStack() 之间的区别?

java - 如何从左到右跟踪和移动字符串?

string - 如何在多行中打破 YAML 中的字符串?

lua - 很棒的 wm/恶意小部件 : using a format function throws a bad argument error

loops - for循环期间 key 未存储在lua表中

c++ - 在数组中搜索字符串