2012-11-13 18 views
0

我正在开发我的小新手项目。项目由两个脚本组成。脚本编号1是从用户接收参数的命令行界面。脚本编号2创建笛卡尔积,并将其写入文本文件。我的想法是使所有的工作都不用将任何东西放在一个文件中)。当我尝试使用 '负载' 我得到这个错误:”如何把两个ruby脚本放到一个工作程序中?

Carthese_product.rb:3:in `<top (required)>': undefined local variable or method 
`x_min' for main:Object (NameError) 
     from D:/Cli_file.rb:25:in `load' 
     from D:/Cli_file.rb:25:in `<main>' 

SCRIPT1(Cli_file.rb):

require 'trollop' 
    opts = Trollop::options do 
    banner <<-EOS 
Welcome to points generator! 

Usage: 
     test [options] <filenames>+ 
where [options] are: 
EOS 
    opt :x_min,    "Minimal value of X", :type => :int 
    opt :x_max,    "Maximal value of X", :type => :int 
    opt :y_min,   "Minimalna wartosc Y", :type => :int 
    opt :y_max,    "Maksymalna wartosc Y", :type => :int 
    opt :interval,   "Interval between points", :type => :int, :default => 1 
    opt :products_file,  "Name of products_file", :type => :string, :default =>  
          "Products"  
    end 

a= opts 
x_min = a[:x_min] 
x_max = a[:x_max] 
y_min = a[:y_min] 
y_max = a[:y_max] 
interval = a[:interval] 
products_file = a[:products_file] 
load 'Carthese_product.rb' 

SCRIPT2(Carthese_product.rb)

products = [] 

(x_min/interval..x_max/interval).each do |x| 
(y_min/interval..y_max/interval).each do|y| 
products << [x*interval,y*interval] 
end 
end 
a = products.map.with_index{|w, i| "#{i+1} #{w[0].to_s} #{w[1].to_s} \n"} 

aFile = File.new(products_file, "w+") 
if aFile 
    a.each{|x| aFile.write(x)} 
else 
puts "Something wrong!" 
end 

我知道最简单的办法就是把所有内容放到一个脚本中,但是为了我的教育目的,我想找另一种方式!感谢您的帮助& intrest!

回答

2

您正试图使用​​局部变量将数据从一个脚本传递到另一个脚本。它不起作用,因为当在顶层定义时,局部变量具有文件范围,因此不能从单独的文件访问。

您必须为您的代码创建适当的接口,以便您可以从其他脚本引用它。创建一个实现了笛卡尔乘积模块:

# cartesian.rb 

module Cartesian 
    extend self 

    def product(x_range, y_range, interval = 1) 
    [].tap do |products| 
     x_range.step interval do |x| 
     y_range.step interval do |y| 
      products << [x, y] 
     end 
     end 
    end 
    end 
end 

现在,require这个文件在你的命令行应用程序的可执行文件,请在命令行中给出的数据,写你的输出:

#/usr/bin/env ruby 
require 'cartesian' 

# Option parsing 

Cartesian.product(x_min..x_max, y_min..y_max, interval).each do |product| 
    puts "(#{product.first}, #{product.last})" 
end 

我建议印刷该程序的输出到标准输出流。这样,如果您想要,可以轻松地将输出重定向到文件:

./cartesian-product $ARGUMENTS > product.list 
0

局部变量不会从一个文件传播到另一个文件。为此,您必须在$前加上全局变量。然后您可以运行Cli_file.rb来运行这两个脚本。

你的脚本现在变成:

Cli_file.rb

require 'trollop' 
opts = Trollop::options do 
banner <<-EOS 
Welcome to points generator! 

Usage: 
    test [options] <filenames>+ 
where [options] are: 
EOS 
    opt :x_min,    "Minimal value of X", :type => :int 
    opt :x_max,    "Maximal value of X", :type => :int 
    opt :y_min,   "Minimalna wartosc Y", :type => :int 
    opt :y_max,    "Maksymalna wartosc Y", :type => :int 
    opt :interval,   "Interval between points", :type => :int, :default => 1 
    opt :products_file,  "Name of products_file", :type => :string, :default =>  
         "Products"  
end 

a= opts 
$x_min = a[:x_min] 
$x_max = a[:x_max] 
$y_min = a[:y_min] 
$y_max = a[:y_max] 
$interval = a[:interval] 
$products_file = a[:products_file] 
load 'Carthese_product.rb' 

Carthese_product.rb

products = [] 

($x_min/$interval..$x_max/$interval).each do |x| 
($y_min/$interval..$y_max/$interval).each do|y| 
products << [x*$interval,y*$interval] 
end 
end 
a = products.map.with_index{|w, i| "#{i+1} #{w[0].to_s} #{w[1].to_s} \n"} 

aFile = File.new($products_file, "w+") 
if aFile 
    a.each{|x| aFile.write(x)} 
else 
    puts "Something wrong!" 
end 

使用全局变量不去做,虽然最好的办法。所以除非这是一次性的,否则你最好重构你的代码。

+2

严格来说,这是正确的。但是,全局变量并不是一种强有力的方式来传递状态。依赖于全局变量的方法依赖于外部代码的副作用,而不是依赖于形式化指定和记录的参数。它们也会不必要地泄露调用代码不应该关注自己并导致线程问题的数据。对于像这样的小剧本可能没问题,但请不要鼓励人们养成坏习惯。 –

+0

我意识到这一点,但由于您已经提供了更好的方法,OP可以选择他想要的任何一个。 – rohit89