我正在学习 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
它工作正常。