【问题标题】:ruby - how to correctly parse varying numbers of command line argumentsruby - 如何正确解析不同数量的命令行参数
【发布时间】:2012-02-24 17:45:54
【问题描述】:

n00b 问题提醒! 这是问题所在: 我正在创建一个至少需要 3 个参数的 shell 脚本:一个字符串、一个行号和至少一个文件。

我编写了一个脚本,它可以接受正好 3 个参数,但我不知道如何处理多个文件名参数。

这是我的代码的相关部分(跳过写回文件等):

#!/usr/bin/env ruby

the_string = ARGV[0] 
line_number = ARGV[1]
the_file = ARGV[2] 

def insert_script(str, line_n, file)
  f = file
  s = str
  ln = line_n.to_i

  if (File.file? f)
    read_in(f,ln,s)
  else 
    puts "false"
  end
end

def read_in(f,ln,s)
  lines = File.readlines(f)
  lines[ln] = s + "\n"
  return lines
end

# run it
puts insert_script(the_string, line_number, the_file)

现在我知道编写一个遍历所有参数的块很容易:

ARGV.each do |a|
   puts a 
end

但我只需要循环从 ARGV[2](第一个文件名)到最后一个文件名的参数。

我知道必须 - 至少 - 至少有一种简单的方法可以做到这一点,但我现在看不出它是什么!

无论如何-如果有人可以向我指出教程或示例,我会非常高兴,我敢肯定那里有很多-但我似乎找不到它们。

谢谢

【问题讨论】:

  • 大家的好答案!感谢大家。通常情况下,我理解或可以使用我在这里得到的许多答案 - 所以要么我变得更聪明,要么这是一个特别简单的问题,要么你们只是很好的解释者......或者这三者的组合!干杯,B

标签: ruby command-line arguments


【解决方案1】:

看看 OptionParser - http://ruby-doc.org/stdlib-1.9.3/libdoc/optparse/rdoc/OptionParser.html。它允许您指定参数的数量,无论它们是强制性的还是可选的,处理诸如 MissingArgument 或 InvalidOption 之类的错误。

【讨论】:

  • 感谢 Sergey - 我确实遇到了 OptionParser,但发现它有点吓人......我敢肯定,它可能非常强大,但我正在寻找 sarnold 建议的确切类型的解决方案。
【解决方案2】:

如果您修改ARGV 数组以删除您不再对视为文件名感兴趣的元素,您可以treat all remaining elements as filenames and iterate over their contents with ARGF

那是满口的,一个小例子会更容易演示:

argf.rb:

#!/usr/bin/ruby

str = ARGV.shift
line = ARGV.shift

ARGF.each do |f|
    puts f
end
$ ./argf.rb one two argf.rb argf.rb 
#!/usr/bin/ruby

str = ARGV.shift
line = ARGV.shift

ARGF.each do |f|
    puts f
end
#!/usr/bin/ruby

str = ARGV.shift
line = ARGV.shift

ARGF.each do |f|
    puts f
end
$ 

argf.rb 文件有两个 副本打印到控制台,因为我在命令行上两次输入了文件名argf.rb。每次提及都会打开并迭代一次。

如果你想将文件作为文件来操作,而不是读取它们的内容,你可以简单地修改ARGV数组,然后直接使用剩余的元素。

【讨论】:

  • 那是完美的——正是我正在寻找的东西,并且很容易被我的 n00bie 大脑所掌握。非常感谢!
【解决方案3】:

您会考虑使用有用的宝石吗? Trollop 非常适合命令行解析,因为它会自动为您提供帮助消息、长短命令行开关等。

require 'trollop'

opts = Trollop::options do
  opt :string, "The string", :type => :string
  opt :line, "line number", :type => :int
  opt :file, "file(s)", :type => :strings
end

p opts 

当我称它为“commandline.rb”并运行它时:

$ ruby commandline.rb --string "foo bar" --line 3 --file foo.txt bar.txt

{:string=>"foo bar", :line=>3, :file=>["foo.txt", "bar.txt"], :help=>false, :string_given=>true, :line_given=>true, :file_given=>true}

【讨论】:

    【解决方案4】:

    如果您不想使用另一个库或更改 ARGV 数组,另一种(而且有点丑陋)的技巧是使用 .upto

    2.upto(ARGV.length-1) do |i|
        puts ARGV[i]
    end
    

    【讨论】:

    • 感谢 Retief - 我和我的一个朋友今晚想出了这个策略,但没有那么优雅......更多的是(在伪代码中):'for 2 to length-1做...'等等,这更简洁 - 干杯。
    【解决方案5】:

    规范的方式是使用shift,像这样:

    the_string = ARGV.shift
    line_number = ARGV.shift
    ARGV.each do |file|
      puts insert_script(the_string, line_number, the_file)
    end
    

    【讨论】:

      猜你喜欢
      • 2011-05-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-27
      • 1970-01-01
      • 1970-01-01
      • 2013-03-21
      相关资源
      最近更新 更多