if, elif, else problemy z instrukcją w Bash

358

Nie mogę ustalić, na czym ifpolega problem z poniższym stwierdzeniem w odniesieniu do elifi then. Pamiętaj, że printfwciąż jest w fazie rozwoju. Po prostu nie byłem jeszcze w stanie tego przetestować w oświadczeniu, więc jest to prawdopodobnie błąd.

Występuje błąd:

./timezone_string.sh: line 14: syntax error near unexpected token `then'
./timezone_string.sh: line 14: `then'

I takie jest zdanie.

if [ "$seconds" -eq 0 ];then
   $timezone_string="Z"
elif[ "$seconds" -gt 0 ]
then
   $timezone_string=`printf "%02d:%02d" $seconds/3600 ($seconds/60)%60`
else
   echo "Unknown parameter"
fi
StuStirling
źródło
7
Zastanawiam się, dlaczego trzeba się thenoświadczenie if, a elifjednak nie else, a także w ogóle.
@ w17t, ponieważ musimy oddzielić warunek od sekwencji.
Sasha
3
@codeforester Nie widzę wiele logiki w oznaczaniu pytania o 50000 wyświetleń jako duplikatu do tego, który ma tylko 5K
fedorqui „SO przestań krzywdzić”
Korzystanie z niektórych narzędzi do automatycznego formatowania kodu może pomóc, automatycznie dodając / usuwając spacje wokół nawiasów. Możesz wyszukać wtyczki do swojego edytora.
Nj Subedi

Odpowiedzi:

453

Brakuje miejsca między elifi [:

elif[ "$seconds" -gt 0 ]

Powinien być

elif [ "$seconds" -gt 0 ]

Ponieważ widzę, że to pytanie zyskuje wiele wyświetleń, ważne jest, aby wskazać, że następująca składnia to:

if [ conditions ]
# ^ ^          ^

co oznacza, że wokół nawiasów potrzebne są spacje . W przeciwnym razie to nie zadziała. Wynika to z faktu [, że samo to polecenie.

Powodem, dla którego nie widzisz coś podobnego elif[: command not found(lub podobny) jest to, że po obejrzeniu ifi then, powłoka szuka albo elif, elsealbo fi. Znajduje jednak inną then(po źle sformatowanym elif[). Dopiero po przeanalizowaniu instrukcji zostanie ona wykonana (i zostanie wyświetlony komunikat o błędzie podobny do elif[: command not foundtego).

fedorqui „SO przestań szkodzić”
źródło
33
Powodem, dla którego nawiasy potrzebują spacji, jest to, że są tylko skrótami do rzeczywistych programów (przynajmniej pierwszy nawias, drugi to po prostu cukier syntaktyczny, tak jak go rozumiem). Aby to zrozumieć, zobacz rzeczywistą stronę dla lewego nawiasu:$ man [
Michael Johansen
3
Czy ten post nie powinien być zamknięty jako literówka?
zx8754,
3
@ zx8754 mógł być, ale nie stał się kanonicznym sposobem naprawienia tego błędu, który wygląda dość przydatnie (wyświetlenia 360K i liczenie).
fedorqui „SO przestań krzywdzić”
3
Niektórzy z moich kolegów nie rozumieją pojęcia „spacja” lub „styl kodowania”, więc może to nie być literówka.
juzzlin
3
[jest rodzajem aliasu dla polecenia testowego. Dlatego wymagany jest pusty znak. if test "$seconds" -eq 0; then ... fijest równoważne z if [ "$seconds" -eq 0 ];then ... fi ]. @LeiYang man testjest tym, czego tak naprawdę szukasz
Melicerte
303

Masz kilka problemów ze składnią skryptu. Oto poprawiona wersja:

#!/bin/bash

if [ "$seconds" -eq 0 ]; then
   timezone_string="Z"
elif [ "$seconds" -gt 0 ]; then
   timezone_string=$(printf "%02d:%02d" $((seconds/3600)) $(((seconds / 60) % 60)))
else
   echo "Unknown parameter"
fi
anubhava
źródło
76
Co dziwne, był to jedyny kompletny i prosty konstrukt bash „jeśli-to-jeszcze”, który z łatwością znalazłem podczas wymiany stosów ... dzięki.
Wildcard
1
wcięcie jest opcjonalne. tłumacz może (i powinien) być #!/bin/sh.
3
@ Chinggis6 Całkowity nonsens, tłumacz może być, #!/bin/shale nie musi.
Camusensei,
4
@Camusensei nie jest to całkowity nonsens, ponieważ shmożna go zamiast tego zastosować dla większej kompatybilności (nie wszystkie dystrybucje * nix mają domyślną powłokę bash (niektóre mają ksh lub ash, ale większość z nich zależy od standardu shdziałania). Co więcej, jeśli bash jest specyficzny lub w skrypcie nie są używane zaawansowane funkcje, wówczas jako interpreter należy użyć „sh” (jest to jeszcze jeden powód), ponieważ może on sam obsługiwać skrypt
6
@ Chinggis6 Prawda, zły wybór słów po mojej stronie.
Camusensei
25

[to polecenie (lub wbudowane w niektóre powłoki). Musi być oddzielony spacją od poprzedniej instrukcji:

elif [
choroba
źródło
3
Jest zastąpiony przez wbudowaną bash, ale twoja wiadomość jest nadal poprawna. użyj, type -a [aby to zobaczyć.
Camusensei,
Jest to również plik binarny, który zawsze wydawał mi się dziwny.
mr.zog
4

Poleciłbym zapoznanie się z podstawami warunkowania w bash.

Symbol „[” jest poleceniem i musi poprzedzać go spacją. Jeśli nie podajesz spacji po elifie, system interpretuje elif [ jako szczególną komendę, która zdecydowanie nie jest tym, czego chciałbyś w tej chwili.

Stosowanie:

elif(A COMPULSORY WHITESPACE WITHOUT PARENTHESIS)[(A WHITE SPACE WITHOUT PARENTHESIS)conditions(A WHITESPACE WITHOUT PARENTHESIS)]

Krótko mówiąc, edytuj segment kodu, aby:

elif [ "$seconds" -gt 0 ]

Wszystko będzie dobrze bez błędów kompilacji. Twój końcowy segment kodu powinien wyglądać następująco:

#!/bin/sh    
if [ "$seconds" -eq 0 ];then
       $timezone_string="Z"
    elif [ "$seconds" -gt 0 ]
    then
       $timezone_string=`printf "%02d:%02d" $seconds/3600 ($seconds/60)%60`
    else
       echo "Unknown parameter"
    fi
Pan Weirdo
źródło
2

Brak miejsca między programem elifa [resztą jest poprawny. musisz to poprawić i sprawdź. tutaj jest ustalony program:

#!/bin/bash

if [ "$seconds" -eq 0 ]; then
   timezone_string="Z"
elif [ "$seconds" -gt 0 ]; then
   timezone_string=$(printf "%02d:%02d" $((seconds/3600)) $(((seconds / 60) % 60)))
else
   echo "Unknown parameter"
fi

przydatny link związany z tym bashem, jeśli indziej

John Walsh
źródło