如何在rake任务的字符串参数中使用逗号?

时间:2011-08-31 14:06:42

标签: ruby rake command-line-interface rakefile

我有以下 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\

我目前正在使用此pull request to rake中提出的解决方法,但有没有办法在不修补rake的情况下完成此操作?

9 个答案:

答案 0 :(得分:8)

改变rake是一个非常脏的修复。请尝试使用OptionParser。语法如下

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

--是跳过解析参数的rake方式所必需的

以及红宝石代码:

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's code
end

答案 1 :(得分:6)

我不确定这是可能的。查看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 :(得分:3)

您是否尝试使用,转义\

答案 3 :(得分:3)

Eugen already answered,为什么它不起作用。

但也许以下解决方法可能会对您有所帮助:

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\"]

至少在windows下,必须屏蔽“(或')。如果没有,它们已被删除,直到字符串达到Rake :: Aplication(可能是shell替换)

答案 4 :(得分:3)

Rake任务变量一般不是很方便,而是使用环境变量:

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

答案 5 :(得分:1)

# rake -v 10.5

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

就像一个魅力。

答案 6 :(得分:0)

另一个简单的解决方法是在参数中使用不同的分隔符。

交换管道非常简单字符(或另一个)而不是逗号分隔的args。在这种情况下,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]

答案 7 :(得分:0)

我们可以将每个字符串转换为符号, 如,

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'

答案 8 :(得分:0)

对于rake版本12.3.2,

  

rake test_commas [“ foo \,bar”]

效果很好