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 $gpodwójnych cudzysłowów; to ogólnie dobra praktyka. Ściśle, nawiasy nie są potrzebne, ponieważ pierwszeństwo -ai -osprawia, że nawet bez nich poprawić.
Zauważ, że operatory -ai -osą częścią specyfikacji POSIX test, aka [, głównie dla kompatybilności wstecznej (ponieważ na przykład były częścią testwersji 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 -ai -oz 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 autoconfnarzę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 thenblokach.
test([), a nie przez powłokę. Powłoka ocenia tylko status wyjścia[.