红宝石
在Unix克隆的PATH中找到awk。
p = ENV['PATH'].split ':'
# Find an executable in PATH.
def find_exec(name)
p.find {|d| File.executable? File.join(d, name)}
end
printf "%s is %s\n", 'awk', find_exec('awk')
糟糕!
$ ruby21 find-awk.rb
find-awk.rb:5:in `find_exec': undefined method `find' for nil:NilClass (NoMethodError)
from find-awk.rb:8:in `<main>'
从错误中我们知道p.find
称为nil.find
,因此p
必须nil
。这怎么发生的?
在Ruby中,def
它具有局部变量的作用域,并且永远不会从外部范围获取局部变量。因此,分配p = ENV['PATH'].split ':'
不在范围内。
未定义的变量通常会导致NameError
,但这p
是特例。Ruby有一个名为的全局方法p
。因此p.find { ... }
成为一个方法调用,如p().find { ... }
。如果p
没有参数,则返回nil
。(高尔夫球手将代码p
用作的快捷方式nil
。)然后nil.find { ... }
加注NoMethodError
。
我通过用Python重写程序来修复它。
import os
import os.path
p = os.environ['PATH'].split(':')
def find_exec(name):
"""Find an executable in PATH."""
for d in p:
if os.access(os.path.join(d, name), os.X_OK,
effective_ids=True):
return d
return None
print("%s is %s" % ('awk', find_exec('awk')))
有用!
$ python3.3 find-awk.py
awk is /usr/bin
我可能希望将其打印出来awk is /usr/bin/awk
,但这是一个不同的错误。