简体   繁体   English

Ruby脚本从特定的行或方法开始

[英]Ruby script start from a specific line or method

Let's say i have a script: 假设我有一个脚本:

!#usr/bin/ruby

# step 1
puts "That's first"
# some code

#step 2
puts "That's second"
# some code

Is there a way to pass ARGV to script that will start execution from a specific line (or step, or class, or whatever)? 有没有办法将ARGV传递给将从特定行(或步骤,类或其他)开始执行的脚本? For example executing $ ruby script.rb -s 2 will start from second step. 例如,执行$ ruby script.rb -s 2将从第二步开始。

I have a thought about parsing the argument with if\\else , but in this case script will become much more complicated and not DRY at all. 我想过用if\\else解析参数,但在这种情况下脚本将变得更加复杂而根本不会干。

Any ideas? 有任何想法吗?

Here's a program run_from_line.rb which accepts three arguments: path and start line, and end line. 这是一个程序run_from_line.rb ,它接受三个参数:path和start line,以及end line。 End line is optional and defaults to -1. 结束行是可选的,默认为-1。

#/usr/bin/env ruby

path = ARGV.shift
program_text = File.readlines(path)
start_line = ARGV.shift.to_i;
end_line = ARGV.shift || '-1'
end_line = end_line.to_i

selected_code = program_text[start_line..end_line].join
eval selected_code

With this script at test.rb : test.rb使用此脚本:

puts "line 0"
puts "line 1"
puts "line 2"

Testing: 测试:

> ruby run_from_line.rb test.rb 1
line 1
line 2

> ruby run_from_line.rb test.rb 1 1
line 1

If you want to make this a system-wide script, run chmod a+x run_from_line.rb then sudo mv run_from_line.rb /usr/local/sbin 如果要将其设置为系统范围的脚本,请运行chmod a+x run_from_line.rb然后运行sudo mv run_from_line.rb /usr/local/sbin

Bad things happen when you use GOTO. 使用GOTO时会发生不好的事情

Here's a proposal that could solve your problem in a bit more elegant way : 这是一个可以更优雅地解决您的问题的提案:

Define your steps in 'define_steps.rb' : 在'define_steps.rb'中定义您的步骤:

# define_steps.rb
#####################################################
@steps = []

def step(i, &block)
  @steps[i] = block
end

def launch_steps!(min = 0, max = @steps.size - 1)
  @steps[min..max].each.with_index(min) do |block, i|
    if block
      puts "Launching step #{i}"
      block.call
    end
  end
end
#####################################################

step 1 do
  puts 'Step 1 with lots of code'
end

step 2 do
  puts 'Step 2 with lots of code'
end

step 3 do
  puts 'Step 3 with lots of code'
end

step 4 do
  puts 'Step 4 with lots of code'
end

Launch them separately with launch_steps.rb : 使用launch_steps.rb单独启动它们:

# launch_steps.rb
require_relative 'define_steps'

launch_steps!
puts "-----------------"
launch_steps!(2,3)

It outputs : 它输出:

Launching step 1
Step 1 with lots of code
Launching step 2
Step 2 with lots of code
Launching step 3
Step 3 with lots of code
Launching step 4
Step 4 with lots of code
-----------------
Launching step 2
Step 2 with lots of code
Launching step 3
Step 3 with lots of code

launch_steps! without parameters runs every defined step, launch_steps!(min,max) runs every step between min and max , launch_steps!(min) runs step min and every step after. 如果没有参数运行每个定义的步骤,则launch_steps!(min,max)minmax之间的每一步运行, launch_steps!(min)运行步骤min和后面的每一步。

There are ways as the answer of max shows you, but you shouldn't do it. 有一些方法,因为max的答案显示你,但你不应该这样做。 There were questions about a goto statement for Ruby before you know. 在您知道之前,有关于Ruby的goto语句的问题。 Why should you go back to the techniques used in BASIC ? 为什么要回到BASIC中使用的技术? Show us a usage and we'll show you better ways. 向我们展示一种用法,我们将向您展示更好的方法。

If you are begining with Ruby and programming you can just use a procedural way of programming like 如果你开始使用Ruby和编程,你可以使用程序化的编程方式

def print_a
  puts "a"
end

and later on, no matter where the line of "puts a" has moved to in between you last update 然后,无论“放一个”的位置在你最后更新之间移动到哪里

print_a

If you are more experienced you'll use this with a combination of Object Oriented or Functional way of programming. 如果您更有经验,那么您将结合使用面向对象或功能性编程方法。

One acceptional use comes me in to mind: conditional require 's or load's 一个接受用途让我想到:条件要求或负载

if condition
  require ./mycode_only_to be_executed_in_this_case.rb'
end

Hope I got you rethinking your question.. 希望我让你重新思考你的问题..

EDIT after comment op 在评论后编辑

The example you refer to isn't DRY, that is the first thing that I' m noticing. 你提到的例子不是DRY,这是我注意到的第一件事。 See https://en.wikipedia.org/wiki/Don 't_repeat_yourself for a definition of DRY 有关DRY的定义,请参阅https://en.wikipedia.org/wiki/Don't_repeat_yourself

Here what I would make of it, I still use a methods to envelop my code so that it is code that I can reuse and has only one purpose and is testable: connect to a site. 在这里我要做的是,我仍然使用一种方法来包含我的代码,以便它是我可以重用的代码,只有一个目的并且是可测试的:连接到一个站点。 No duplicate code, so DRY. 没有重复的代码,所以DRY。

require 'watir'

def goto_site site
  a = Watir::Browser.new :chrome
  a.goto site
  # a lot of code down here
  a.close
end

goto_site 'site.com'

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM