【问题标题】:How can I use a comma in a string argument to a rake task?如何在 rake 任务的字符串参数中使用逗号?
【发布时间】:2011-11-07 15:49:23
【问题描述】:

我有以下 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 的情况下完成此操作?

【问题讨论】:

    标签: ruby rake command-line-interface rakefile


    【解决方案1】:

    对于 rake 版本 12.3.2,

    rake test_commas["foo\,bar"]

    效果很好

    【讨论】:

      【解决方案2】:

      # rake -v 10.5

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

      像魅力一样工作。

      【讨论】:

        【解决方案3】:

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

        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'

        【讨论】:

          【解决方案4】:

          您是否尝试过使用\ 转义,

          【讨论】:

          • 是的,这对我也不起作用(在上述任何情况下)。我会用一个例子来更新这个问题。
          • 工作就像一个魅力!
          【解决方案5】:

          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
          

          【讨论】:

          • 谢谢!这里提供的所有选项都有些脏和/或丑陋,但这是迄今为止最快的。
          【解决方案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 中没有。

          【讨论】:

          • 现在已经不是这样了。逗号现在可以用 \ 转义
          【解决方案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】:

            更改 rake 是一个相当肮脏的修复。尝试改用OptionParser。语法如下

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

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

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

            【讨论】:

            • 从实现的角度来看,这是一种非常干净的方法。从可用性的角度来看,我习惯于使用 -- 将选项与参数分开,尤其是使用 git,所以不得不使用 -- 然后将参数视为选项感觉很奇怪。但话又说回来,如果我关心可用性,我可能只是使用自定义 CLI 或使用 thor :)
            【解决方案9】:

            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替换)

            【讨论】:

            • 如果我事先知道输入格式,这是一个很好的解决方法,但在这种情况下,我可以只命名参数,以便 rake -T 更具描述性。
            • 我添加了一个新版本 - 它更接近您的建议。
            • 这值得作为上游补丁提交,以便您可以在字符串中包含逗号。使用带有否定后视的正则表达式(匹配前面没有斜杠的逗号)而不是使用 MYSEP 怎么样?
            • 我用正则表达式做了一些实验,但没有成功。然后我太累了,无法继续......我会第二次寻找它。
            • 我至少为制作的逗号版本替换了 MYSEP。对于“中的参数,我实际上没有更好的主意。
            猜你喜欢
            • 2019-02-22
            • 2015-10-24
            • 1970-01-01
            • 1970-01-01
            • 2018-08-22
            • 2017-09-28
            • 1970-01-01
            • 1970-01-01
            • 2016-12-22
            相关资源
            最近更新 更多