我遇到了一个从 CLI(不在框架中)调用的 ruby 脚本的问题,在尝试打开它时会导致 ENOENT 错误(文件不存在),但仅在使用 gsub 正则表达式替换构建文件名时. 当字符串由任何其他方法构造时,它可以工作。我敢肯定,我做错了很简单,但是我花了很长时间才弄清楚。
系统信息
# lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 12.04.3 LTS
Release: 12.04
Codename: precise
# rvm -v
rvm 1.23.13 (stable) by Wayne E. Seguin <wayneeseguin@gmail.com>, Michal Papis <mpapis@gmail.com> [https://rvm.io/]
# ruby -v
ruby 2.0.0p195 (2013-05-14 revision 40734) [x86_64-linux]
Filesystem: ext2
Permissions:
# ls -lah /home/boise/config
total 24K
drwxr-xr-x 2 boise boise 4.0K Nov 13 19:40 .
drwxr-xr-x 11 boise boise 4.0K Nov 13 20:22 ..
-rwxr-xr-x 1 boise boise 248 Nov 13 09:31 boise.yaml
-rwxr-xr-x 1 boise boise 335 Nov 13 19:35 config.rb
-rwxr-xr-x 1 boise boise 339 Nov 13 20:06 stanford.yaml
-rwxr-xr-x 1 boise boise 248 Nov 13 09:49 test.yaml
user being used to run scripts and owns containing directory is 'boise'
there is nothing abnormal about the file system here, no symbolic links or
mappings or anything like that.
我启动了一个简单的脚本来重现错误。在此,我将其简化为尽可能简单,将路径的前缀设为静态并使用绝对路径,这样就没有关于相对路径或当前工作目录的问题。
脚本名称:测试
#!/usr/bin/env ruby
require 'yaml'
# Here we are "hardcoding" the values.
$config_yaml = "boise.yaml"
puts $config_yaml
config_filespec = "/home/boise/config/#{$config_yaml}"
puts config_filespec
puts File.exists? config_filespec
$configuration = YAML.load(File.open(config_filespec))
$verbose = true
hosts = []
args = []
puts $config_yaml
ARGV.each do |arg|
if arg.match /hosts\=(.*?)/i
hosts = ARGV.delete(arg).gsub(/hosts\=(.*?)/i,'\2').split(',')
elsif arg == "quiet"
$verbose = false
ARGV.delete(arg)
elsif arg.match /cfg=(.*?)/
#Here the value of the YAML file to be loaded is set with a regular expression substitution.
$config_yaml = ARGV.delete(arg).gsub(/cfg=(.*?)/, "\2")
else
end
end
#do the same output as we did the first time hardcoded, but this time the
#value got reset by a gsub -- same variable, same name, etc
puts $config_yaml
config_filespec = "/home/boise/config/#{$config_yaml}"
puts config_filespec
puts File.exists? config_filespec
$configuration = YAML.load(File.open(config_filespec))
这可以按预期工作:
# ./testing
boise.yaml
/home/boise/config/boise.yaml
true
boise.yaml
boise.yaml
/home/boise/config/boise.yaml
true
但是请注意当我将 yaml 字符串作为命令行参数传递时会发生什么。请注意,这甚至是完全相同的文件名!
# ./testing cfg=boise.yaml
boise.yaml
/home/boise/config/boise.yaml
true
boise.yaml
boise.yaml
/home/boise/config/boise.yaml
false
./testing:31:in `initialize': No such file or directory - /home/boise/config/boise.yaml (Errno::ENOENT)
from ./testing:31:in `open'
from ./testing:31:in `<main>'
我还尝试使用 String(config_filespec)、config_filespec.to_s 强制转换字符串,并使用 + "" 进行字符串连接,希望这是字符串与文字或正则表达式或类似的一些类型问题。有任何想法吗?
提前感谢堆栈溢出!