2012-02-02 8 views
5

Powiadomienie o zapytaniu n00b! tutaj jest problem: Tworzę skrypt powłoki, który pobiera co najmniej 3 argumenty: ciąg, numer linii i co najmniej jeden plik.ruby ​​- jak poprawnie przeanalizować zmienną liczbę argumentów linii poleceń:

Napisałem skrypt, który akceptuje DOKŁADNIE 3 argumenty, ale nie wiem, jak obsługiwać wiele argumentów nazwy pliku.

oto odpowiednie części mojego kodu (z pominięciem zapisu z powrotem do pliku 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) 

teraz wiem, że to łatwo napisać blok, który będzie iterację wszystkich argumentów:

ARGV.each do |a| 
    puts a 
end 

, ale potrzebuję TYLKO przechodzić przez args z ARGV [2] (pierwsza nazwa pliku) do ostatniej nazwy pliku.

Wiem, że musi istnieć - przynajmniej jeden prosty sposób, aby to zrobić, ale po prostu nie widzę, co to jest w tej chwili!

w każdym razie - Byłbym bardziej niż szczęśliwy, gdyby ktoś mógł po prostu wskazać mi tutorial lub przykład, jestem pewien, że jest ich wiele - ale nie mogę ich znaleźć.

dzięki

+0

wielkie odpowiedzi od wszystkich! Dziękuję wszystkim. Zazwyczaj nie jest tak, że rozumiem lub mogę korzystać z wielu odpowiedzi, które tu dostaję - więc albo robię się mądrzejszy, albo to było szczególnie łatwe pytanie, albo jesteście dobrymi tłumaczami ... albo jakimś kombinatem wszystkich trzech! Pozdrawiam, B –

Odpowiedz

5

Jeśli zmodyfikujesz tablicę ARGV, aby usunąć elementy, które nie są już dłużej traktowane jako nazwy plików, możesz treat all remaining elements as filenames and iterate over their contents with ARGF.

To kęs, mały przykład Zademonstruje łatwiej:

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 
$ 

Istnieje dwa kopie pliku argf.rb drukowane na konsoli, ponieważ Podałem nazwę pliku argf.rb dwa razy w linii poleceń. Został otwarty i powtórzony raz dla każdej wzmianki.

Jeśli chcesz operować plikami jako plikami, zamiast czytać ich zawartość, możesz po prostu zmodyfikować tablicę ARGV, a następnie bezpośrednio użyć pozostałych elementów.

+0

To jest idealne - dokładnie to, czego szukałem i łatwo uchwycone przez mój mózg. dziękuję bardzo! –

2

Spójrz na OptionParser - http://ruby-doc.org/stdlib-1.9.3/libdoc/optparse/rdoc/OptionParser.html. Pozwala na określenie liczby argumentów, niezależnie od tego, czy są one obowiązkowe, czy opcjonalne, obsługują błędy, takie jak MissingArgument lub InvalidOption.

+0

dzięki Sergeyowi - natknąłem się na OptionParser, ale stwierdziłem, że jest trochę onieśmielające ... prawdopodobnie bardzo potężny jestem pewien, ale szukałem dokładnie tego, na co zasugerowałeś. –

6

Czy uważasz za przydatne pomocny klejnot? Trollop jest dobre dla wiersza polecenia parsowania ponieważ automatycznie daje Ci pomóc wiadomości, długie i krótkie przełączników wiersza polecenia, itp

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 

Kiedy ja to nazywam „commandline.rb” i uruchom go:

$ 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 ... Sprawdzę to - dzięki Markowi! –

2

Alternatywna (i nieco brzydsza) sztuczka, jeśli nie chcesz korzystać z innej biblioteki lub zmienić tablicę ARGV, użyj.września

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

dzięki Retief - mój przyjaciel i ja wymyśliliśmy tę strategię dziś, ale nie tak elegancko ... bardziej wzdłuż linii (w pseudokodzie): "dla 2 do długości-1 do ..." itd. to jest bardziej zwięzłe - takie okrzyki. –

3

Kanoniczna sposobem jest użycie shift, tak:

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

dzięki dave, doceń to. –

Powiązane problemy