ruby - 如何正确解析不同数量的命令行参数

发布于 2025-01-01 18:10:34 字数 826 浏览 0 评论 0原文

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

我编写了一个脚本,它将接受 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] 中的参数(第一个文件名)到最后一个文件名。

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

无论如何 - 如果有人能给我指出一个教程或示例,我会非常高兴,我确信那里有很多 - 但我似乎找不到它们。

谢谢

n00b question alert!
here is the problem:
I am creating a shell script that takes a minimum of 3 arguments: a string, a line number, and at least one file.

I've written a script that will accept EXACTLY 3 arguments, but I don't know how to handle multiple file name arguments.

here's the relevant parts of my code (skipping the writing back into the file etc):

#!/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)

now I know that it's easy to write a block that will iterate through ALL the arguments:

ARGV.each do |a|
   puts a 
end

but I need to ONLY loop through the args from ARGV[2] (the first file name) to the last file name.

I know there's got to be - at a minimum - at least one easy way to do this, but I just can't see what it is at the moment!

in any case - I'd be more than happy if someone can just point me to a tutorial or an example, I'm sure there are plenty out there - but I can't seem to find them.

thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

红衣飘飘貌似仙 2025-01-08 18:10:34

您会考虑使用有用的宝石吗? 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}

Would you consider using a helpful gem? Trollop is great for command line parsing because it automatically gives you help messages, long and short command-line switches, etc.

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 

When I call it "commandline.rb" and run it:

$ 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}
長街聽風 2025-01-08 18:10:34

如果您修改 ARGV 数组以删除不再作为文件名处理的元素,您可以 将所有剩余元素视为文件名,并使用 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 数组,然后直接使用其余元素。

If you modify the ARGV array to remove the elements you're no longer interested in treating as filenames, you can treat all remaining elements as filenames and iterate over their contents with ARGF.

That's a mouthful, a small example will demonstrate it more easily:

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
$ 

There are two copies of the argf.rb file printed to the console because I gave the filename argf.rb twice on the command line. It was opened and iterated over once for each mention.

If you want to operate on the files as files, rather than read their contents, you can simply modify the ARGV array and then use the remaining elements directly.

离旧人 2025-01-08 18:10:34

规范的方法是使用 shift,如下所示:

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

The canonical way is to use shift, like so:

the_string = ARGV.shift
line_number = ARGV.shift
ARGV.each do |file|
  puts insert_script(the_string, line_number, the_file)
end
海未深 2025-01-08 18:10:34

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

Take a look at OptionParser - http://ruby-doc.org/stdlib-1.9.3/libdoc/optparse/rdoc/OptionParser.html. It allows you to specify the number of arguments, whether they are mandatory or optional, handle errors such as MissingArgument or InvalidOption.

日暮斜阳 2025-01-08 18:10:34

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

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

An alternate (and somewhat uglier) trick if you don't want to use another library or change the ARGV array is to use .upto

2.upto(ARGV.length-1) do |i|
    puts ARGV[i]
end
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文