2010-08-12 11 views
7

Próbowałem uruchamiać polecenia za pomocą potoków.Jak uruchamiać polecenia skryptów ze zmiennych?

Podstawowe:

single="ls -l" 
$single 

który działa zgodnie z oczekiwaniami

Pipes:

multi="ls -l | grep e" 
$multi 
ls: |: No such file or directory 
ls: grep: No such file or directory 
ls: e: No such file or directory 

... nic dziwnego

bash < $multi 

$multi: ambiguous redirect 

obok spróbować

bash $multi 
/bin/ls: /bin/ls: cannot execute binary file 

Tylko

echo $multi > tmp.sh 
bash tmp.sh 

pracował.

Czy istnieje sposób wykonywania bardziej złożonych poleceń bez tworzenia skryptu do wykonania?

+0

patrz [BashFAQ/050] (http://mywiki.wooledge.org/BashFAQ/050). –

Odpowiedz

11

Demonstrujesz różnicę między powłoką a jądrem.

"ls -l" jest wykonywalne przez wywołanie systemowe execve(). Możesz uzyskać man execve w celu uzyskania szczegółowych informacji, ale to prawdopodobnie zbyt dużo szczegółów dla Ciebie.

"ls -l | grep e" wymaga interpretacji powłoki, aby skonfigurować potok. Bez użycia powłoki, "|" znak jest po prostu przekazywany do execve() jako argument do ls. Dlatego widzisz błędy "Brak takiego pliku lub katalogu".

Rozwiązanie:

cmd="ls -l | grep e" 
bash -c "$cmd" 
+0

Dzięki, jakikolwiek pomysł dlaczego "bash -c" drukuje dane wyjściowe w jednym wierszu? Chciałbym mieć ten sam wynik, jaki wprowadzono ręcznie w wierszu poleceń. – stacker

+0

@stacker Nie sądzę, że to prawda.Otrzymuję taki sam wynik, jak w linii poleceń. Być może twój grep zwraca tylko jedną linię? – bukzor

+0

To się stało, ponieważ zapomniałem ująć zmienną w podwójne cudzysłowy. – stacker

-3

gdy chcesz wykonywać polecenia z rur, wystarczy uruchomić go. Nigdy nie umieszczaj polecenia w zmiennej i spróbuj go uruchomić. Wystarczy wykonać go

ls -l |grep

Jeśli chcesz przechwytywać dane wyjściowe, należy użyć $()

var=$(ls -l |grep ..)

+0

Polecenia pochodzą z innego serwera i powinny zostać wykonane na maszynie docelowej. W związku z tym nie może być trudne kodowane. – stacker

+0

patrz http://mywiki.wooledge.org/BashFAQ/050 – ghostdog74

0

Musisz heredoc to zrobić poprawnie. W odpowiedzi na POSIX compliant way to see if a function is defined in an sh script, szczegółowo opisałem, jak odczytywać skrypt w zmiennej, programowo analizować go pod kątem informacji i/lub modyfikować w razie potrzeby, a następnie uruchamiać z innego skryptu lub funkcji powłoki. To jest w zasadzie to, co próbujemy zrobić, a heredoc umożliwia ponieważ zapewnia deskryptor pliku:

% multi='ls -l | grep e' 
% sh <<_EOF_ 
> ${multi} 
> _EOF_ 
< desired output > 

że rozwiąże swój prosty przykład sprawy. Zobacz moją drugą odpowiedź na więcej.

-Mike

Powiązane problemy