2011-08-03 16 views
26

Ok to doprowadza mnie do szału shell:Ruby uciec argumentu argv lub ciąg znaków jako argument polecenia

`ls #{"/media/music/Miles Davis"}` 

nie z powodu przestrzeni pomiędzy "Miles" i "Davis"

Say piszę rubin skrypt i użytkownik przekazuje ścieżkę pliku jako argument. W jaki sposób mogę go uniknąć i przekazać do polecenia powłoki. Tak, tak, wiem, należy unikać wystrzałów. Ale jest to wymyślny przykład, nadal tego potrzebuję.

Zrobiłbym system("ls", ARGV[0]), ale nie zwraca wyjściowego wyjścia ls jako napis, co jest tym, co robią dobrze.

W jaki sposób można uciec, niezależnie od tego, co wstawia się do wyjścia?

Odpowiedz

51

Zastosowanie require 'shellwords' i Shellwords.escape, który będzie naprawić tego rodzaju rzeczy dla ciebie:

http://apidock.com/ruby/Shellwords/shellescape

+2

Doskonała! Dziękuję Ci! Nie wiedziałem o tym module. – ulver

+0

Możesz także użyć skrótu 'String # shellescape', tak: ' ls # {"/ media/music/Miles Davis" .shellescape} ' – cgenco

-2

cudzysłowach działa również:

`ls "#{'/media/music/Miles Davis'}"` 

lub

`ls "#{ARGV[0]}"` 
+0

Nie rób tego. Rozważmy: 'a =„-l”| wc -l # "'; ' ' 'ls "# {a}"' ' – Mike

+0

Działa to dla przestrzeni, ale nie stanowi ciąg ma'"', '$' lub kilka innych znaków – Carpetsmoker

6

St ay dalej od budowania ciągów powłoki ilekroć to możliwe, jest to doskonały wektor do wykonywania dowolnego kodu.

W tym przypadku można użyć popen, co robi ucieczki dla Ciebie:

IO.popen(['printf', 'a b']) do |f| 
    var = f.read 
end 
+1

Powinno to mieć więcej upvotes, popen pozwala również na wydrukowanie strumienia odpowiedzi raczej wygodnie np. while (line = f.gets) {puts line}. – vise

+0

Oto jeszcze bardziej kompaktowa wersja: 'IO.popen ([" plik "," --brief "," --mime-type ", untrustworthy_input], w:: close, err:: close) .read' – aidan

Powiązane problemy