Prosty problem. Mam taki kawałek kodu w Bashu:
for ARG in "${@}" ; do
case "${ARG}" in
"x")
echo "Processing x..."
shift
;;
"y")
echo "Processing y..."
shift
if test "${#}" != "0" ; then
shift "${#}"
echo "Warning: Some arguments have been skipped"
fi
;;
esac
done
Załóżmy, że jest on w pliku run
. Jeśli wywołuję go tak:
./run x y
to wynik jest zgodny z moimi oczekiwaniami:
Processing x...
Processing y...
Ale jeśli wywołuję go z odwróconą kolejnością argumentów:
./run y x
to powinien zgodnie z moimi oczekiwaniami nie przetwarzać argumentu x
– powinien on zostać opuszczony, "przesunięty", "wyshiftowany" – i wynik powinien być taki:
Processing y...
Warning: Some arguments have been skipped
Natomiast rzeczywisty wynik mówi, że argument ten jest przetwarzany:
Processing y...
Warning: Some arguments have been skipped
Processing x...
Dlaczego Bash tak robi?
UPDATE:
Co ciekawe, jeśli wyświetlać listę argumentów przed przetworzeniem poszczególnych z nich w ten sposób:
for ARG in "${@}" ; do
echo '${@}' == "${@}"
# tu reszta kodu
done
to wynikowa jej zawartość w przypadkach obu wywołań jest taka, jak oczekiwana przeze mnie:
Wywołanie ./run x y
:
${@} == x y
Processing x...
${@} == y
Processing y...
Wywołanie ./run y x
(odwrócona kolejność argumentów):
${@} == y x
Processing y...
Warning: Some arguments have been skipped
${@} ==
Processing x... # Skąd? Przecież lista jest pusta, jak widać wyżej…
To powoduje uszczegółowienie mojego problemu z tym kodem: dlaczego Bash przetwarza pustą listę argumentów tak, jakby nie była pusta?