Ruby eval在irb和文件中的行为不同

此代码适用于irb:

irb(main):037:0> eval < nil irb(main):041:0> puts machine host => nil irb(main):042:0> puts attribute machine => nil irb(main):043:0> 

但是,当我尝试执行与ruby脚本相同的代码时,我收到以下错误:

 ../autosys/convert_jil_to_zapp.rb:40: undefined local variable or method `machine' for main:Object (NameError) from ../autosys/convert_jil_to_zapp.rb:29:in `each_line' from ../autosys/convert_jil_to_zapp.rb:29 from ../autosys/convert_jil_to_zapp.rb:27:in `each' from ../autosys/convert_jil_to_zapp.rb:27 pi929c1n10 /ms/user/h/hirscst/ruby/autosys 77$ gvim try.rb pi929c1n10 /ms/user/h/hirscst/ruby/autosys 78$ chmod +x try.rb pi929c1n10 /ms/user/h/hirscst/ruby/autosys 79$ ./try.rb host ./try.rb:8: undefined local variable or method `machine' for main:Object (NameError) 

任何人都能解释为什么

这是因为在运行eval时尚未定义machine变量。 一个更简洁的例子:

在IRB中工作,但不是作为脚本

 eval 'x = 3' puts x # throws an exception when run as a script => 3 

适用于IRB和脚本

 x = 1 eval 'x = 3' puts x => 3 

引用Matz :

局部变量应该在编译时确定,因此首先在eval’ed字符串中定义的局部变量只能从其他eval’ed字符串访问。 另外,它们在Ruby2中会更加短暂,因此不会从外部访问这些变量。

不同之处在于,在IRB中, 所有内容都被评估,因此它们都在相同的范围内。 也就是说,你基本上是在IRB中这样做的:

 eval 'x = 3' eval 'puts x' 

它既适用于IRB,也适用于脚本。

因为您在IRB中定义了一个名为machine的方法或变量,但在Ruby脚本中却没有。