Klasyczna technika (metaznaki ucieczki):
if [ \( "$g" -eq 1 -a "$c" = "123" \) -o \( "$g" -eq 2 -a "$c" = "456" \) ]
then echo abc
else echo efg
fi
Odwołuję się do $g
podwójnych cudzysłowów; to ogólnie dobra praktyka. Ściśle, nawiasy nie są potrzebne, ponieważ pierwszeństwo -a
i -o
sprawia, że nawet bez nich poprawić.
Zauważ, że operatory -a
i -o
są częścią specyfikacji POSIX test
, aka [
, głównie dla kompatybilności wstecznej (ponieważ na przykład były częścią test
wersji 7.IX UNIX), ale są wyraźnie oznaczone przez POSIX jako „przestarzałe”. Bash (zobacz wyrażeń warunkowych ) wydaje się wywłaszczyć klasyczne i POSIX znaczenia dla -a
i -o
z własnych operatorów alternatywnych, które przyjmują argumenty.
Z pewną ostrożnością możesz użyć bardziej nowoczesnego [[
operatora, ale pamiętaj, że wersje w Bash i Korn Shell (na przykład) nie muszą być identyczne.
for g in 1 2 3
do
for c in 123 456 789
do
if [[ ( "$g" -eq 1 && "$c" = "123" ) || ( "$g" -eq 2 && "$c" = "456" ) ]]
then echo "g = $g; c = $c; true"
else echo "g = $g; c = $c; false"
fi
done
done
Przykład uruchomienia przy użyciu Bash 3.2.57 na Mac OS X:
g = 1; c = 123; true
g = 1; c = 456; false
g = 1; c = 789; false
g = 2; c = 123; false
g = 2; c = 456; true
g = 2; c = 789; false
g = 3; c = 123; false
g = 3; c = 456; false
g = 3; c = 789; false
Nie musisz cytować zmiennych, [[
jak to robisz, [
ponieważ nie jest to osobne polecenie w taki sam sposób [
.
Czy to nie jest klasyczne pytanie?
Tak bym pomyślał. Istnieje jednak inna alternatywa, a mianowicie:
if [ "$g" -eq 1 -a "$c" = "123" ] || [ "$g" -eq 2 -a "$c" = "456" ]
then echo abc
else echo efg
fi
Rzeczywiście, jeśli przeczytasz wytyczne „przenośnej powłoki” dla autoconf
narzędzia lub powiązanych pakietów, ta notacja - używanie „ ||
” i „ &&
” - jest tym, co zalecają. Przypuszczam, że mógłbyś nawet posunąć się tak daleko:
if [ "$g" -eq 1 ] && [ "$c" = "123" ]
then echo abc
elif [ "$g" -eq 2 ] && [ "$c" = "456" ]
then echo abc
else echo efg
fi
Tam, gdzie działania są tak trywialne jak echo, nie jest to złe. Gdy blok akcji, który ma być powtarzany, składa się z wielu wierszy, powtórzenie jest zbyt bolesne i preferowana jest jedna z wcześniejszych wersji - lub musisz zawinąć akcje w funkcję wywoływaną w różnych then
blokach.
test
([
), a nie przez powłokę. Powłoka ocenia tylko status wyjścia[
.