Pomiędzy następującymi alternatywami ...
z
eval
.comd="ls" eval "$comd"
z
source /dev/stdin
printf "ls" | source /dev/stdin
z
source /dev/stdin
i( )
lub{ }
( printf "ls" ) | source /dev/stdin { printf "ls"; } | source /dev/stdin
(Gdy prowadzimy
printf
w{ }
, jest tam żadnych korzyści inne niż nie używając powłoki w tle?)Jaka jest różnica między nimi?
Który jest preferowany?
Jaki jest preferowany sposób uruchamiania poleceń?
()
czy{}
?
bash
command-line
MS.Kim
źródło
źródło
Odpowiedzi:
z
bash manpage
:Nie ma różnic między tymi dwoma sposobami.
Jest tylko jedna uwaga:
eval
łączy wszystkie argumenty, które są następnie uruchamiane jako pojedyncze polecenie.source
odczytuje zawartość pliku i wykonuje je.eval
może budować polecenia tylko na podstawie swoich argumentów, a niestdin
. Więc nie możesz tego zrobić:Twój przykład zapewnia ten sam wynik, ale cel
eval
isource
jest inny.source
jest zwykle używany do udostępniania biblioteki dla innych skryptów, natomiasteval
służy wyłącznie do oceny poleceń. Jeślieval
to możliwe, należy unikać używania , ponieważ nie ma gwarancji, że ewaluowany ciąg jest czysty;subshell
zamiast tego musimy przeprowadzić kontrolę poczytalności .Kiedy uruchamiasz polecenia sekwencji w nawiasach klamrowych
{ }
, wszystkie polecenia są uruchamiane w bieżącej powłoce , a nie w podpowłoce (tak jest w przypadku uruchamiania w nawiasach (patrz odniesienie do bash )).Korzystanie
subshell ( )
zużywa więcej zasobów, ale nie wpływa to na bieżące środowisko. Użycie{ }
uruchamia wszystkie polecenia w bieżącej powłoce, więc wpływa to na środowisko. W zależności od celu możesz wybrać jeden z nich.źródło
eval
przezsource
. Myślę, że pytanie brzmi: jesteval "$cmd"
równoważneecho "$cmd" | source /dev/stdin
. Moja obecna opinia brzmi: tak.Główną różnicą jest to, że druga i trzecia forma używają potoku, który zmusi bash do uruchomienia polecenia „source” w podpowłoce (chyba że ustawiona jest ostatnia rura, dostępna tylko w bash 4.2+), co sprawi, że będzie ona prawie odpowiednikiem :
Konsekwencje są takie, że wszelkie zmienne środowiskowe ustawione przez kod zostaną utracone, więc nie będzie działać zgodnie z oczekiwaniami:
Aby uruchomić polecenia w bieżącej powłoce, możesz użyć podstawienia procesu:
Możesz umieścić więcej poleceń w nawiasach, używając zwykłego średnika.
Jeśli wyeliminujesz potok w ten sposób, uważam, że nie ma różnicy między użyciem „eval” i „source”. Powinieneś wybrać ten, który jest łatwiejszy w użyciu w konkretnym przypadku:
źródło
Jako uzupełnienie już udzielonych odpowiedzi:
source
Odpowiednik ...... jest ...
W przypadku
ls
nie ma znaczącej różnicy.Ale w przypadku polecenia, które ma wpłynąć na twoje obecne środowisko (co zwykle zamierzasz podczas używania
source
), ten wariant zrobiłby to (podobnie jak twoje pierwsze rozwiązanieeval
), podczas gdy twoje drugie podejście tylko wpływa na środowisko podpowłoki, która wygrała będą dostępne po wykonaniu linii kodu.źródło