Вы не используете OptionParser правильно несколькими способами.
При определении параметров вы должны указать местозаполнитель для фактического значения параметра. Если вы этого не сделаете, это будет интерпретироваться как переключатель, возвращая либо true, либо false в зависимости от того, был ли установлен переключатель.
opts.on('-h', '--host HOST', 'The host to run ssh session with') do |host|
options[:host] = "#{host}"
end
Другая ошибка состоит в том, что вы определили -h
для хоста и опции пользователя. Вам лучше определить другую букву для каждого из них, вы, вероятно, намеревались иметь -u
для пользователя в любом случае.
Но основная проблема, вызвавшая ошибку, заключается в том, что вы обрабатываете возвращаемое значение метода #parse!
, как если бы оно возвращало анализируемые значения. Но возвращаемое значение фактически является остатком массива ARGV
, который не был согласован с синтаксическим анализатором. И поскольку вы пытаетесь получить к нему доступ, как хэш, попросив элемент по символу, он жалуется, что к элементам массива обращаются только значения Integer. Чтобы исправить это, просто сохраните ссылку options
и не присваивайте ей возвращаемое значение.
ARGV.parse!
С этого момента, я дам вам некоторую дополнительную критику, но то, что я буду рекомендовать не должно быть причиной каких-либо ошибок:
Кроме того, вы могли бы пропустить значения нулевых по умолчанию предоставленных вами в Хеш в начале, если вы спросите Hash для неопределенного ключа, вы все равно дадите вам нуль.
options = {
host: 'localhost'
}
Я бы сказал, называя #parse!
на аргумент массива ARGV
командной строки, в то время как это, кажется, вариант, чтобы сделать это, не очень очевидна. Я бы рекомендовал сохранить ссылку на парсер переменной и вызвать метод в синтаксическом анализаторе.
parser = OptionParser.new do |opts|
…
end
parser.parse!(ARGV)
Если вы хотите, вы можете даже назвать это без аргумента, он будет использовать ARGV
по умолчанию. Но это, по моему мнению, еще раз затруднит понимание вашего кода.
И вы также можете избавиться от преобразования строк значений через интерполяцию.По крайней мере, когда вы фактически получаете свои значения из массива аргументов командной строки ARGV
, вы можете быть абсолютно уверены, что все элементы будут объектами String. Однако, если вы намереваетесь кормить парсер другими массивами, которые не полностью построены с помощью строковых элементов, вы должны сохранить преобразование.
opts.on('-h', '--host HOST', 'The host to run ssh session with') do |host|
options[:host] = host
end
Также обратите внимание, что есть очень, очень распространенное соглашение, что вы используете ровно два пространства для каждого уровня отступа в Ruby-кода. В ваших примерах вы используете четыре и восемь пробелов, которые многим рубистам очень не понравится. Дополнительную информацию см. В разделе The Ruby styleguide.
Вот исправленная версия кода:
#!/usr/bin/env ruby
require 'optionparser'
options = {
host: 'localhost'
}
parser = OptionParser.new do |opts|
opts.banner = 'Usage: ruby-remote-tailer.rb [options]'
opts.on('-h', '--host HOST', 'The host to run ssh session with') do |host|
options[:host] = host
end
opts.on('-u', '--user USER', 'The user account that will run the session') do |user|
options[:user] = user
end
opts.on('-f', '--file FILE', 'The file to run the tail on') do |file|
options[:file] = file
end
end
parser.parse!(ARGV)
puts options[:host]
Какой выход из 'ставит options'? – Atri
Выход будет остальным ARGV. Элементы, которые не соответствовали какому-либо из блоков .on. См. Мой ответ для полного объяснения. – aef