2013-04-24 56 views
0

我正在使用Ruby來執行一個代碼,它採用命令行參數。 現在我試圖使用不同的選項相同的程序,所以我把選項放在一個文件中,我希望程序讀取每行解釋選項並相應地執行程序。OptionParser解析參數的形式文件,而不是命令行

但我得到這個錯誤。 「C:/Ruby193/lib/ruby/1.9.1/optparse.rb:1348:block in parse_in_order': undefined method shift」for「--c execue --query unix --Servername abc123」:String(NoMethodError)「

i理解它讀取文件並將該行視爲字符串。但是想知道是否有辦法克服這種移位錯誤,並將該行看作是在命令提示符下輸入的。或者更好的解決方案。

這是我的代碼。

require 'optparse' 
require 'micro-optparse' 
# --command execue --query unix command --Servername abc123 
f =File.open("list_of_commands.txt", "r") 
f.each_line { |line| 
line= line.chomp 
#line = "--c execue --query unix --Servername abc123" 
#line = eval("\"#{line}\"") 
puts line 

options = {} 
OptionParser.new do |opts| 

    opts.on("-c", "--command result,execue,chart,scpfile", String, "Single command to execute ") do |c| 
    options[:comd] = c 
    end 

    opts.on("-q", "--query remote command, unix command", String, "performs the command on local or remote machine") do |q| 
    options[:query] = q 
    end 

    opts.on("-s", "--servername CHSXEDWDC002 ", String, "server name to execute the command") do |v| 
    options[:hname] = v 
    end 

    opts.on_tail('-h', '--help', 'Show this message') do 
    puts opts 
    exit 
    end 

end.parse!(line) 
p options 
} 

該文件的內容是以下 --c execue --query UNIX --servername ABC123

我還試圖用微optparse但面臨同樣的錯誤。任何解決方法?

更新: 根據「@mu太短」的建議,我嘗試下面的選項。 (「#{Shellwords.shellsplit(line)}」)和/或 end.parse!(Shellwords.shellsplit(line))。 但他們都沒有工作。

我還嘗試使用「line = line.split(」\ t「)」將數據行拆分爲數組,然後使用end.parse!(line)。出把儘可能 --c execue --query UNIX --servername ABC123

,但現在我得到的塊錯誤:無效選項--C執行

更新:#2 看着錯誤,問題是用錯誤的參數(-c但由於用戶「@mu太短」的建議使用陣列

更新:3 傳遞數組只工作編輯了諸如-c之類的參數的簡短格式,但是當長格式被提供時,它以失敗的參數erorr失敗。

我沒有看到有關optparse的文檔。我甚至試過微解析,但它requres默認valuves和它不是我的選擇:(

回答

2

parse!方法,希望有一個數組作爲它的參數,而不是一個字符串。你可能需要使用Shellwords.shellsplit而非String#split(或類似手卷法),以您的轉換line到一個數組,以防萬一你要處理的引用和諸如此類事情是這樣的:

OptionParser.new do |opts| 
    #... 
end.parse!(Shellwords.shellsplit(line)) 
+0

嗨感謝您的快速回復。我試過這些選項。 end.parse!(「#{Shellwords.shellsplit(line)}」)和end.parse!(Shellwords.shellsplit(line))。但他們都沒有工作。我也嘗試使用「line = line.split(」\ t「)」然後end.parse!(line)將行分割爲數組。但不是我得到'塊在

':無效選項 - c執行 user2300908 2013-04-24 22:25:29

+1

您的'opts.on'參數看起來不適合'--c'選項。當你可能指' - 命令'時,爲什麼你有'--Command'? – 2013-04-24 22:54:04

+0

該問題還沒有完全解決,通過傳遞數組我可以使用參數的簡短形式,但是當傳遞長的形式我得到錯誤爲「無效的選項: - 命令執行(OptionParser :: InvalidOption)。是我我使用命令而不是命令 – user2300908 2013-04-25 06:46:57

1

雖然你可以把你的命令行參數到一個文件中,標誌和所有,有更好的方法來記住配置設置。

而不是存儲標誌,請使用YAML文件。 YAML是一種很好的數據格式,可以輕鬆轉換爲Ruby哈希和對象。「Yaml Cookbook」是一個非常有用的頁面,用於學習Ruby的格式的來龍去脈。有許多其他語言的YAML解析器,可以很容易地共享這些設置,這隨着系統的增長而變得非常有用。

使用一點創意代碼,您可以使用YAML作爲基本設置,並讓CLI標誌覆蓋存儲的設置。

如果你不熟悉YAML,很容易使用類似以獲取有關文件的開始:

require 'yaml' 

data = { 
    'command' => %w[result execute chart scpfile], 
    'query' => ['remote command', 'unix command'], 
    'servername' => 'CHSXEDWHDC002', 
} 

puts data.to_yaml 

,輸出:

--- 
command: 
- result 
- execute 
- chart 
- scpfile 
query: 
- remote command 
- unix command 
servername: CHSXEDWHDC002 

重定向輸出到結尾的文件在.yaml,你在路上。

要閱讀它放回腳本中使用:

require 'yaml' 

data = YAML.load_file('path/to/data.yaml') 

快速往返試驗表明:

require 'yaml' 

data = { 
    'command' => %w[result execute chart scpfile], 
    'query' => ['remote command', 'unix command'], 
    'servername' => 'CHSXEDWHDC002', 
} 

YAML.load(data.to_yaml) 

它看起來像:

{"command"=>["result", "execute", "chart", "scpfile"], 
"query"=>["remote command", "unix command"], 
"servername"=>"CHSXEDWHDC002"} 

如果你想有默認值,存儲在YAML文件中,並用命令行標誌覆蓋它們,從文件中讀取數據,然後使用該結果荷蘭國際集團的對象爲基準,爲OptionParse:

require 'optparse' 
require 'yaml' 

# Note, YAML can deal with symbols as keys, but other languages might not like them. 
options = { 
    :comd => %w[result execute chart scpfile], 
    :query => ['remote command', 'unix command'], 
    :hname => 'CHSXEDWHDC002', 
} 

# we'll overwrite the options variable to pretend we loaded it from a file. 
options = YAML.load(options.to_yaml) 

OptionParser.new do |opts| 

    opts.on("-c", "--Command result,execue,chart,scpfile", String, "Single command to execute ") do |c| 
    options[:comd] = c 
    end 

    opts.on("-q", "--query remote command, unix command", String, "performs the command on local or remote machine") do |q| 
    options[:query] = q 
    end 

    opts.on("-s", "--Servername CHSXEDWHDC002 ", String, "server name to execute the command") do |v| 
    options[:hname] = v 
    end 

    opts.on_tail('-h', '--help', 'Show this message') do 
    puts opts 
    exit 
    end 

end.parse! 

那不是測試,但我們在工作中做類似的事情的時候,所以它保存到一個文件,它用棍子一會兒戳,看看有什麼你想出來。

+0

我喜歡使用yaml文件的想法,會給它一個鏡頭 – user2300908 2013-04-25 04:43:26

+0

我想你會喜歡它的。我們有一些大的配置,由多個相關的應用程序使用,允許我們定義公共數據目錄,所有應用程序必須知道的隊列名稱,數據庫主機等。 – 2013-04-25 04:54:40