如何从字符串中删除行以Lua中的特定字符串开头?

时间:2013-10-06 10:19:23

标签: string lua lua-patterns

如何从字符串中删除行以Lua中的另一个字符串开头?例如,我想删除字符串result中的所有行,以<Table开头。这是我到目前为止编写的代码:

for line in result:gmatch"<Table [^\n]*" do line = "" end

4 个答案:

答案 0 :(得分:1)

string.gmtach用于获取所有模式。要替换某些模式,您需要使用string.gsub

另一个问题是,您的模式<Table [^\n]*会匹配包含单词<Table的所有行,而不只是从它开始。

Lua模式不支持行锚的开始,这几乎可以工作:

local str = result:gsub("\n<Table [^\n]*", "")

除了它会错过第一行。我的解决方案是使用第二次运行来测试第一行:

local str1 = result:gsub("\n<Table [^\n]*", "")
local str2 = str1:gsub("^<Table [^\n]*\n", "")

答案 1 :(得分:1)

LPEG库非常完美 为了这种任务。 只需编写一个函数来创建自定义线条剥离器:

local mk_striplines
do
  local lpeg      = require "lpeg"
  local P         = lpeg.P
  local Cs        = lpeg.Cs
  local lpegmatch = lpeg.match

  local eol       = P"\n\r" + P"\r\n" + P"\n" + P"\t"
  local eof       = P(-1)
  local linerest  = (1 - eol)^1 * (eol + eof) + eol

  mk_striplines = function (pat)
    pat               = P (pat)
    local matchline   = pat * linerest
    local striplines  = Cs (((matchline / "") + linerest)^1)
    return function (str)
      return lpegmatch (striplines, str)
    end
  end
end

请注意mk_striplines()的参数可以是字符串或a 图案。 因此结果非常灵活: mk_striplines (P"<Table" + P"</Table>")会创建一个脱衣舞娘 用两种不同的模式丢弃线条。 mk_striplines (P"x" * P"y"^0)以a开头删除每一行 x后跟任意数量的y - 你明白了。

用法示例:

local linestripper = mk_striplines "foo"

local test = [[
foo lorem ipsum
bar baz
buzz
foo bar
xyzzy
]]

print (linestripper (test))

答案 2 :(得分:1)

其他答案提供了从字符串中实际剥离行的良好解决方案,但没有解决为什么代码无法执行此操作的原因。

为了清晰起见,重新格式化,您写道:

for line in result:gmatch"<Table [^\n]*" do 
    line = "" 
end

第一部分是迭代result并提取以<Table开头的所有文本范围的合理方式,并继续但不包括下一个换行符。 gmatch返回的迭代器在每次调用时返回匹配文本的副本,局部变量line保存for循环体的副本

由于匹配文字已复制到line,因此对line所做的更改不会,也无法修改result中存储的实际文字。

这是由于Lua字符串的一个更基本的属性。 Lua中的所有字符串都是不可变的。存储后,无法更改。保存字符串的变量实际上是一个指向内部引用计数表的不可变字符串的指针,它只允许两个操作:新字符串的内化,以及没有剩余引用的内化字符串的删除。

因此,任何编辑result中存储的字符串内容的方法都需要创建一个全新的字符串。其中string.gmatch提供对内容的迭代但不允许更改内容,string.gsub提供了新字符串的创建,其中与模式匹配的所有文本都已被新内容替换。但即使string.gsub也没有改变不可变的源文本;它正在创建一个新的不可变字符串,它是旧的替换字符串的副本。

使用gsub可能就像这样简单:

result = result:gsub("<Table [^\n]*", "")

但这将揭示模式本身的其他缺陷。首先,最明显的是,没有任何要求模式仅在行的开头匹配。其次,该模式不包括换行符,因此它将使该行存在但是为空。

所有这些都可以通过仔细和巧妙地使用模式库来改进。但它并没有改变您从XML文本开始并且不使用XML感知工具处理它的事实。在这种情况下,任何基于模式匹配或甚至正则表达式的方法都可能以泪流满面。

答案 3 :(得分:0)

result = result:gsub('%f[^\n%z]<Table [^\n]*', '')

此模式的开头'%f[^\n%z]前沿模式,它将匹配从换行符或零字符到另一个字符的任何转换,对于前沿模式,前置模式字符计为零字符。换句话说,使用该前缀允许模式的其余部分在第一行或任何其他行首开头匹配。

参考:the Lua 5.3 manual, section 6.4.1 on string patterns