Chociaż jest alias
to jeden ze sposobów, można to zrobić eval
również za pomocą - po prostu nie tyle chcesz eval
wykonania polecenia, ile chceszeval
deklaracji polecenia .
podoba mi się alias
es - używam ich cały czas, ale bardziej lubię funkcje - szczególnie ich zdolność do obsługi parametrów i że niekoniecznie muszą być one rozszerzane w pozycji poleceń, jak jest to wymagane dla alias
es.
Pomyślałem więc, że może też chcesz spróbować:
_time() if set -- "${IFS+IFS=\$2;}" "$IFS" "$@" && IFS='
'; then set -- "$1" "$2" "$*"; unset IFS
eval "$1 $TIME ${3#"$1"?"$2"?}"
fi
Chodzi $IFS
głównie o to $*
. Ważne jest, aby wynik ( subshell bit )
był również wynikiem rozszerzenia powłoki, a więc w celu rozwinięcia argumentów w parsowalny ciąg, którego używam "$*"
(nie eval
"$@"
, nawiasem mówiąc, chyba że jesteś pewien, że wszystkie argumenty można połączyć spacjami) . Rozdzielony separator między argumentami "$*"
jest pierwszym bajtem wejściowym $IFS
, więc kontynuowanie pracy bez pewności co do jej wartości może być niebezpieczne. Tak więc funkcja zapisuje $IFS
, ustawia ją na \n
ewline wystarczająco długo, aby set ... "$*"
w "$3"
, unset
s, a następnie resetuje swoją wartość, jeśli wcześniej miała taką.
Oto małe demo:
TIME='set -x; time'
_time \( 'echo "$(echo any number of subshells)"' \
'command -V time' \
'hash time' \
\) 'set +x'
Widzisz, umieściłem w poleceniu dwie wartości $TIME
- dowolna liczba jest w porządku - nawet żadna - ale upewnij się, że została poprawnie zmieniona i zacytowana - i to samo dotyczy argumentów _time()
. Wszystkie zostaną połączone w jeden ciąg komend, gdy zostaną wykonane - ale każdy argument otrzymuje własny \n
ewline, dzięki czemu można je stosunkowo łatwo rozłożyć. W przeciwnym razie możesz zebrać je wszystkie w jednym, jeśli chcesz, i rozdzielić je na \n
ewline lub średniki lub co tam masz. Po prostu upewnij się, że pojedynczy argument reprezentuje polecenie, które możesz swobodnie umieścić w swoim wierszu w skrypcie podczas jego wywoływania.\(
, na przykład jest w porządku, o ile w końcu zostanie zastosowane \)
. Zasadniczo normalne rzeczy.
Po eval
otrzymaniu powyższego fragmentu wygląda on następująco:
+ eval 'IFS=$2;set -x; time (
echo "$(echo any number of subshells)"
command -V time
hash time
)
set +x'
A jego wyniki wyglądają jak ...
WYNIK
+++ echo any number of subshells
++ echo 'any number of subshells'
any number of subshells
++ command -V time
time is a shell keyword
++ hash time
bash: hash: time: not found
real 0m0.003s
user 0m0.000s
sys 0m0.000s
++ set +x
hash
Błąd wskazuje, że nie masz /usr/bin/time
zainstalowanego (bo nie) i command
niech nas nie wie czym jest uruchomiony. Trailing set +x
jest kolejną komendą wykonywaną po time
(co jest możliwe) - ważne jest, aby zachować ostrożność przy komendach wejściowych podczas eval
pisania czegokolwiek.