2009-11-19 13 views
5

Chcę napisać skrypt foo, który po prostu wywołuje bar z dokładnie tymi samymi argumentami, z którymi został wywołany, używając Basha lub Perla.Jak mogę uzyskać niezmodyfikowane argumenty wiersza poleceń, aby "zawinąć" inne narzędzie wiersza poleceń?

Teraz, po prostu sposób, aby zrobić to w Perl byłoby

#!/bin/perl 

my $args=join(' ', @ARGV); 
`bar $args`; 

Jednak wartości w ARGV zostały już przetworzone przez powłokę, więc jeśli zadzwonię

foo "I wonder, \"does this work\"" 

bar będzie nazywaj się w ten sposób:

W jaki sposób mogę uzyskać oryginalny wiersz poleceń, aby móc go po prostu przekazać dosłownie?

Odpowiedz

11

Nie można uzyskać argumentów do pliku wykonywalnego perl przed przetworzeniem przez powłokę. Można jednak upewnić się, że powłoka nie przetwarza je ponownie:

system('bar', @ARGV); 

vs.

system("bar @ARGV"); 

Zobacz perldoc -f system:

Jeżeli istnieje tylko jeden skalar argument, argument jest sprawdzany dla metaznaków powłoki, a jeśli są jakieś, cały argument jest przekazywany do systemu powłoka poleceń do parsowania (jest to "/ bin/sh -c" na platformach Unix, ale różni się na innych platformach). Jeśli nie ma metaznaków powłoki w argumencie , jest on dzielony na słowa i przekazywany bezpośrednio do "execvp", co jest bardziej wydajne.

Jeśli trzeba przeczytać wyjście z programu, należy użyć dojście procesu i przekazać argumenty w ten sam sposób (bez interpolacji):

open my $barhandle, '-|', 'bar', @ARGV or die "Can't call bar: $!"; 
while (my $line = <$barhandle>) 
{ 
    # do something with $line... 
} 
close $barhandle; 

Istnieje wiele sposobów można nazwać się do programu w Perlu; patrz What's the difference between Perl's backticks, system, and exec? dla dobrego przeglądu głównych opcji.

+0

Jedną z rozważań jest oczywiście to, że wartość zwracana z system() jest wartością zwracaną z wykonania programu, a nie wyjściem z programu. Konieczne może być przekierowanie danych wyjściowych do pliku i odczytanie pliku, jeśli próbujesz zebrać dane wyjściowe. – atk

+0

@atk: w takim przypadku można użyć uchwytu procesu. – Ether

+1

Nie, w takim przypadku użyjesz IPC :: Run lub IPC :: Cmd – ysth

3

To niezwykle proste. Sprawdź systemowy (LIST) wariant wywołań systemowych.

system('bar', @ARGV); 

System perldoc -f

3

W bash:

exec bar "[email protected]" 

ta zachowuje odstępy w argumentach. Jednak przekierowanie we/wy nie jest argumentem w rozumieniu tego terminu (ale przekierowanie we/wy wykonane dla pierwotnego wywołania będzie obowiązywać w wywołanym poleceniu "słupkowym", chyba że zostanie zmienione).

Powiązane problemy