【问题标题】:how break out of scope ruby variable ruby如何突破范围红宝石变量红宝石
【发布时间】:2017-04-01 07:00:56
【问题描述】:

我使用以下代码从文件中删除行:

File.open("#{$whitelist}-tmp", "w") do |outFile|
  File.foreach("#{$whitelist}") do |li|
    outFile.puts li unless li.chomp[/\A#{instanceId}\z/]
    @comm = outFile
  end
end
FileUtils.mv(@comm, $whitelist)

它有效,但我认为这不是正确的方法,因为我必须创建一个额外的变量“@comm”只是为了从循环中传达文件名。如果我直接使用 'outFile' 作为 FileUtils.mv 的第一个参数,我会得到一个未定义的变量错误。

那么,我应该怎么做呢?

提前致谢。

【问题讨论】:

  • 与你的问题无关,"#{$whitelist}"中的"#{...}"是什么目的?
  • 这段代码没有多大意义,IMO。 outFile 因此@comm 是一个File 对象。更重要的是,在块之后,它将是一个closed 文件对象。 FileUtils::mvStrings 作为参数,而不是 Files。我很惊讶它甚至可以正常工作,我希望 TypeErrorraised。
  • @JörgWMittag:确实提高了:TypeError: no implicit conversion of Fixnum into String

标签: ruby variables scope


【解决方案1】:

File.open 上的文档

如果给出了可选代码块,它将作为参数传递打开的文件,并且当块终止时,文件对象将自动关闭。 块的值将从 File.open 返回。

所以我们可以这样做

file = File.open("#{$whitelist}-tmp", "w") do |outFile|
  File.foreach("#{$whitelist}") do |li|
    outFile.puts li unless li.chomp[/\A#{instanceId}\z/]
  end

  outFile # return value of the block
end

FileUtils.mv(file, $whitelist)

更新

是我遗漏了什么还是这段代码只是过滤和重写了文件?如果是这样,它可以大大简化。

filename = $whitelist

content = File.readlines(filename)
filtered = content.grep(/\A#{instanceId}\Z/)
File.write(filename, filtered)

【讨论】:

  • 我不确定 mv 这样的文件句柄是否有效。我当然不会依赖它在未来工作。
  • @JimStewart:是的,文档/代码根本没有暗示使用句柄的可能性。无论如何,我提供了一个改进的版本:)
  • @JimStewart:检查,.mv 在句柄上不起作用。
  • %x|sed s/^#{instanceId}$//g #{$whitelist}| :)
  • 嗯? en.wikipedia.org/wiki/Sed 内联执行。老实说,它可以删除语法较短的行,但我不记得了 :)
【解决方案2】:

最简单的方法是在使用它的块之前分配一个包含文件名的变量:

tempFile = "#{$whitelist}-tmp"
File.open(tempFile, "w") do |outFile|
  File.foreach("#{$whitelist}") do |li|
    outFile.puts li unless li.chomp[/\A#{instanceId}\z/
  end
end
FileUtils.mv(tempFile, $whitelist)

【讨论】:

  • 正如@Jordan 上面评论的那样,您可以简单地使用$whitelist,而无需在第二个File 中使用引号和字符串插值。你也真的不应该使用 $global 变量,就像永远一样。
  • 全局变量适用于较小的实用程序脚本
猜你喜欢
  • 2011-02-04
  • 1970-01-01
  • 2019-08-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-12
  • 2011-05-28
相关资源
最近更新 更多