Как я могу использовать запятую в строковом аргументе для задачи грабли?

У меня есть следующий файл Rakefile:

task :test_commas, :arg1 do |t, args|
  puts args[:arg1]
end

И хочу вызвать его одним аргументом строки, содержащим запятые. Вот что я получаю:

%rake 'test_commas[foo, bar]'
foo

%rake 'test_commas["foo, bar"]'
"foo

%rake "test_commas['foo, bar']"
'foo

%rake "test_commas['foo,bar']"
'foo

%rake "test_commas[foo\,bar]"
foo\

В настоящее время я использую обходное решение, предложенное в этом запросе на тягу для рейка, но есть ли способ сделать это без патча рейка?

Ответ 1

Я не уверен, что это возможно. Рассматривая lib/rake/application.rb, метод для разбора строки задачи:

def parse_task_string(string)
  if string =~ /^([^\[]+)(\[(.*)\])$/
    name = $1
    args = $3.split(/\s*,\s*/)
  else
    name = string
    args = []
  end 
  [name, args]
end 

Похоже, что строка аргументов разделяется запятыми, поэтому вы не можете иметь аргумент, содержащий запятую, по крайней мере, не в текущем rake-0.9.2.

Ответ 2

Изменение грабли - довольно грязное исправление. Вместо этого используйте OptionParser. Синтаксис следующий

$ rake mytask -- -s 'some,comma,sepparated,string'

-- необходимо пропустить метод разборки аргументов

и здесь код ruby:

task :mytask do
  options = {}

  optparse = OptionParser.new do |opts|
    opts.on('-s', '--string ARG', 'desc of my argument') do |str|
      options[:str] = str
    end

    opts.on('-h', '--help', 'Display this screen') do     
      puts opts                                                          
      exit                                                                      
    end 
  end

  begin 
    optparse.parse!
    mandatory = [:str]
    missing = mandatory.select{ |param| options[param].nil? }
    if not missing.empty?
      puts "Missing options: #{missing.join(', ')}"
      puts optparse
      exit
    end

  rescue OptionParser::InvalidOption, OptionParser::MissingArgument
    puts $!.to_s
    puts optparse
    exit  
  end

  puts "Performing task with options: #{options.inspect}"
  # @TODO add task code
end

Ответ 3

Вы пытались выйти из , с помощью \?

Ответ 4

Евгений уже ответил, почему он не работает.

Но, возможно, вам может помочь следующее обходное решение:

task :test_commas, :arg1, :arg2 do |t, args|
  arg = args.to_hash.values.join(',')
  puts "Argument is #{arg.inspect}"
end

Он принимает два аргумента, но соединяет их, чтобы получить "реальный".

Если у вас больше одной запятой, вам нужно больше аргументов.


Я сделал несколько более глубоких исследований и нашел одно (или два) решения. Я не думаю, что это идеальное решение, но похоже, что это работает.

require 'rake'
module Rake
  class Application
    #usage: 
    #   rake test_commas[1\,2\,3]
    def parse_task_string_masked_commas(string)
      if string =~ /^([^\[]+)(\[(.*)\])$/
        name = $1
        args = $3.split(/\s*(?<!\\),\s*/).map{|x|x.gsub(/\\,/,',')}
      else
        name = string
        args = []
      end 
      [name, args]
    end   

    #Usage: 
    #   rake test_commas[\"1,2\",3]
    #" and ' must be masked
    def parse_task_string_combined(string)
      if string =~ /^([^\[]+)(\[(.*)\])$/
        name = $1
        args = $3.split(/(['"].+?["'])?,(["'].+?["'])?/).map{|ts| ts.gsub(/\A["']|["']\Z/,'') }
        args.shift if args.first.empty?
      else
        name = string
        args = []
      end 
      [name, args]
    end   

    #~ alias :parse_task_string :parse_task_string_masked_commas
    alias :parse_task_string :parse_task_string_combined

  end

end
desc 'Test comma separated arguments'
task :test_commas, :arg1  do |t, args|
  puts '---'
  puts "Argument is #{args.inspect}"
end

Версия parse_task_string_masked_commas позволяет звонить с маскированными запятыми:

rake test_commas[1\,2\,3]

Версия parse_task_string_combined позволяет:

rake test_commas[\"1,2,3\"]

По крайней мере, под окнами, "(или" ) должны быть замаскированы. Если нет, они уже удалены до тех пор, пока не будет достигнута строка Rake:: Aplication (возможно, замена оболочки)

Ответ 5

Переменные задачи рейка не очень удобны вообще, вместо этого используют переменные среды:

task :my_task do
  ENV["MY_ARGUMENT"].split(",").each_with_index do |arg, i|
    puts "Argument #{i}: #{arg}"
  end
end

Затем вы можете вызвать

MY_ARGUMENT=foo,bar rake my_task

Или, если вы предпочитаете

rake my_task MY_ARGUMENT=foo,bar

Ответ 6

# rake -v 10.5

rake test_commas\['foo\,bar'\]

работает как шарм.

Ответ 7

Другим простым решением является использование другого разделителя в ваших аргументах.

Это довольно просто заменить на трубу | символ (или другой) вместо ваших аргументов, разделенных запятой. В этом случае Rake корректно анализирует ваши аргументы и позволяет разбить первый для массива.

desc 'Test pipe separated arguments'
task :test_pipes, :arg1, :arg2  do |t, args|
  puts ":arg1 is: #{ args[:arg1] }"
  puts ":arg2 still works: #{ args[:arg2] }"
  puts "Split :arg1 is: #{ args[:arg1].split('|') }"
end

Позвоните по следующему адресу:

rake test_pipes["foo|bar",baz]

Ответ 8

Мы можем преобразовать каждую строку в символ, Как,

task :create do   
ARGV.each { |a| task a.to_sym do ; end }
 puts ARGV[1]
 puts ARGV[2]
 puts ARGV[3]
 puts ARGV[4]     
end
end

выполнить как,

rake create '1, s' '2' 'ww ww' 'w, w'

Ответ 9

Для граблей версии 12.3.2,

rake test_commas["foo\,bar"]

работает хорошо