4

我正在学习 Ruby,但有一个我无法理解的错误。我有一个方法,它接受一个字符串数组(行)并删除所有行,直到包含一个模式的某一行。该方法如下所示:

def removeHeaderLines(lines)
  pattern = "..." # Some pattern.

  # If the pattern is not there, do not drop any lines.
  prefix  = lines.take_while {|line| (not line.match(pattern))}
  if prefix.length == lines.length then
    return prefix
  end

  # The pattern is there: remove all line preceding it, as well as the line
  # containing it.
  suffix  = (lines.drop_while {|line| (not line.match(pattern))}).drop(1)
  return suffix
end

这工作正常,生成的字符串(行)正确显示在我正在生成的网页上。

此外,我想删除模式后面的所有非空行。我已将方法修改如下:

def removeHeaderLines(lines)
  pattern = "..." # Some pattern.

  # If the pattern is not there, do not drop any lines.
  prefix  = lines.take_while {|line| (not line.match(pattern))}
  if prefix.length == lines.length then
    return prefix
  end

  # The pattern is there: remove all line preceding it, as well as the line
  # containing it.
  suffix  = (lines.drop_while {|line| (not line.match(pattern))}).drop(1)

  # Remove leading non-empty lines.
  # ADDING THIS INTRODUCES A BUG.
  body = suffix.drop_while {|line| (line != "")}
  return body
end

非常令人惊讶(至少对我而言)这不起作用。在生成的网页上,我看到的不是内容,而是错误消息:Liquid error: undefined method `[]' for nil:NilClass。

我无法从这条信息中理解多少。据我了解,一些调用我的代码的代码试图访问一个非数组对象,就好像它是一个数组一样。但是我的方法的两个版本都返回一个字符串数组(变量 suffix 和 body 都设置为一个字符串数组),那么为什么会有区别呢?

所以,不幸的是,由于我对 Ruby 的了解很少,我不知道如何调试这个问题。

有人在上面的代码中看到任何错误吗?或者,是否有人对可能导致错误“nil:NilClass 的未定义方法‘[]’”有任何提示?

编辑

附加信息。我正在扩展我自己没有编写的代码(它来自 Octopress,文件 plugins/include_code.rb)。原始渲染代码如下所示:

def render(context)
  code_dir = (context.registers[:site].config['code_dir'].sub(/^\//,'') || 'downloads/code')
  code_path = (Pathname.new(context.registers[:site].source) + code_dir).expand_path
  file = code_path + @file

  if File.symlink?(code_path)
    return "Code directory '#{code_path}' cannot be a symlink"
  end

  unless file.file?
    return "File #{file} could not be found"
  end

  Dir.chdir(code_path) do

    ##################################
    # I have replaced the line below #
    ##################################
    code = file.read

    @filetype = file.extname.sub('.','') if @filetype.nil?
    title = @title ? "#{@title} (#{file.basename})" : file.basename
    url = "/#{code_dir}/#{@file}"
    source = "<figure class='code'><figcaption><span>#{title}</span> <a href='#{url}'>download</a></figcaption>\n"
    source += " #{highlight(code, @filetype)}</figure>"
    safe_wrap(source)
  end
end

我已经更换了线路

code = file.read

code = linesToString(removeHeaderLines(stringToLines(file.read)))

其中两个缺失的方法是:

def stringToLines(string)
  ar = Array.new
  string.each_line {|line| ar.push(line)}

  return ar
end

def linesToString(lines)
  s = ""
  lines.each {|line| s.concat(line)}

  return s
end

我希望这有帮助。

编辑 2

感谢 Hassan 的提示(使用 join 方法)我发现了问题!与 join 方法并行存在一个 split 方法。所以

"A\nB\n".split(/\n/)

["A", "B"]

而通过使用 each_line (就像我所做的那样),可以在每一行末尾加上 '\n' 。作为结果

suffix.drop_while {|line| (line != "")}

删除所有行。结果是一个空字符串,显然使我正在使用的库崩溃。感谢 Hassan 提出了一个更惯用的解决方案。我现在有以下内容:

def removeHeaderLines(code)
  lines = code.split(/\r?\n/)
  pat   = /.../ # Some pattern.
  index = lines.index {|line| line =~ pat}
  lines = lines.drop(index + 1).drop_while {|line| line != ""} unless index.nil?

  lines.join "\n"
end

它工作正常。

4

2 回答 2

2

当您尝试nil像数组(或哈希)一样使用时会发生该异常:

irb(main):001:0> nil[0]
NoMethodError: undefined method `[]' for nil:NilClass
        from (irb):1
        from /home/mslade/rubygems1.9/bin/irb:12:in `<main>'

或在尚未初始化时将变量用作数组(或哈希):

irb(main):005:0> @b[0]
NoMethodError: undefined method `[]' for nil:NilClass
        from (irb):5
        from /home/mslade/rubygems1.9/bin/irb:12:in `<main>'

查找您忽略初始化数组的位置,例如@b = []

如果您实际上没有使用数组,那么您调用的函数可能需要一个。从顶部开始扫描给出的 stak 转储,直到它提到您的代码行。然后调查那条线,看看你可能错过了什么。

于 2012-04-09T14:38:12.400 回答
0

我不知道是什么导致了异常,但是您的代码可能是这样的:

def remove_header_lines(lines)
  pattern = /some pat/
  index = lines.index {|lines| lines =~ pattern}

  lines = lines.drop(index+1).drop_while {|lines| line != ""} unless index.nil?

  lines.join
end
于 2012-04-09T15:26:12.273 回答