2012-02-02 15 views
5

n00b alerta de pregunta! aquí está el problema: Estoy creando un script de shell que toma un mínimo de 3 argumentos: una cadena, un número de línea y al menos un archivo.ruby: cómo analizar correctamente varios números de argumentos de línea de comandos

He escrito una secuencia de comandos que aceptará EXACTAMENTE 3 argumentos, pero no sé cómo manejar múltiples argumentos de nombre de archivo.

aquí es las partes pertinentes de mi código (saltarse la escritura de nuevo en el archivo 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) 

ahora sé que es fácil escribir un bloque que va a recorrer todos los argumentos:

ARGV.each do |a| 
    puts a 
end 

pero necesito SOLO recorrer las args de ARGV [2] (el primer nombre de archivo) hasta el último nombre de archivo.

Sé que tiene que haber, como mínimo, al menos una forma fácil de hacerlo, ¡pero no puedo ver qué es en este momento!

en cualquier caso - Estaría más que feliz si alguien me puede indicar un tutorial o un ejemplo, estoy seguro de que hay mucho por ahí, pero parece que no puedo encontrarlos.

gracias

+0

grandes respuestas de todo el mundo! gracias a todos. no es el caso que entiendo o puedo usar muchas de las respuestas que recibo aquí, entonces o me estoy volviendo más inteligente o esta fue una pregunta particularmente fácil o ustedes son simplemente buenos explicadores ... ¡o alguna combinación de los tres! vítores, B –

Respuesta

5

Si modifica la matriz ARGV para eliminar los elementos que ya no le interesan tratar como nombres de archivo, puede treat all remaining elements as filenames and iterate over their contents with ARGF.

que es un bocado, un pequeño ejemplo demostrará que sea más fácil:

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 
$ 

Hay dos copias del archivo argf.rb impresos a la consola porque Di el nombre de archivo argf.rb dos veces en la línea de comando. Fue abierto e iterado más de una vez por cada mención.

Si desea operar los archivos como archivos, en lugar de leer sus contenidos, simplemente puede modificar la matriz ARGV y luego usar los elementos restantes directamente.

+0

que es perfecto, exactamente lo que estaba buscando y fácilmente captado por mi cerebro n00bie. muchas gracias! –

2

Echa un vistazo a OptionParser - http://ruby-doc.org/stdlib-1.9.3/libdoc/optparse/rdoc/OptionParser.html. Le permite especificar la cantidad de argumentos, ya sean obligatorios u opcionales, que manejen errores como MissingArgument o InvalidOption.

+0

gracias Sergey - Me encontré con OptionParser, pero me pareció un poco intimidante ... probablemente extremadamente poderoso, estoy seguro, pero estaba buscando el tipo exacto de solución que Sarnold sugirió. –

6

¿Consideraría utilizar una joya útil? Trollop es grande para el analizador de la línea de comandos, ya que da automáticamente los mensajes de ayuda, modificadores de línea de comandos largos y cortos, 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 

Cuando lo llamo "commandline.rb" y ejecutarlo:

$ 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} 
+0

hmmm ... Lo comprobaré, gracias Mark! –

2

Un truco alternativo (y algo más feo) si no quieres usar otra biblioteca o cambiar la matriz ARGV es usar.hasta

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

gracias Retief - a un amigo mío y a mí se nos ocurrió esta estrategia esta noche, pero no tan elegante ... más a lo largo de las líneas de (en pseudo-código): 'para 2 a longitud-1 do ...' etc. esto es más conciso, así que ¡salud! –

3

La forma canónica es utilizar shift, así:

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

gracias dave, lo aprecio. –

Cuestiones relacionadas