Snažím se pochopit, jak funguje priorita logického operátora v bash. Například bych očekával, že následující příkaz nebude nic opakovat.
true || echo aaa && echo bbb
Na rozdíl od mého očekávání však bbb se vytiskne.
Může mi někdo prosím vysvětlit, jak mohu dát smysl složenému && a || operátory v bash?
Přijatá odpověď:
V mnoha počítačových jazycích jsou operátory se stejnou prioritou asociativní vlevo. To znamená, že při absenci seskupovacích struktur se nejprve provádějí operace zcela vlevo. Bash není výjimkou z tohoto pravidla.
To je důležité, protože v Bash && a || mají stejnou přednost.
Ve vašem příkladu se tedy stane, že operace zcela vlevo (|| ) se provede jako první:
true || echo aaa
Protože true je zjevně pravda, || zkratuje operátor a celé tvrzení je považováno za pravdivé bez nutnosti vyhodnocovat echo aaa jak byste očekávali. Nyní zbývá provést operaci zcela vpravo:
(...) && echo bbb
Vzhledem k tomu, že první operace byla vyhodnocena jako true (tj. měla stav ukončení 0), je to jako byste spouštěli
true && echo bbb
takže && nezkratuje, což je důvod, proč vidíte bbb ozvalo se.
Stejné chování byste získali s
false && echo aaa || echo bbb
Poznámky založené na komentářích
- Upozorňujeme, že pravidlo levé asociativnosti je pouze následuje, když oba operátory mají stejné přednost. To není případ, kdy tyto operátory používáte ve spojení s klíčovými slovy jako
[[...]]nebo((...))nebo použijte-oa-aoperátory jako argumenty protestnebo[příkazy. V takových případech AND (&&nebo-a) má přednost před NEBO (||nebo-o). Děkujeme komentáři Stephana Chazelase za objasnění tohoto bodu. -
Zdá se, že v jazycích C a C podobných
&&má vyšší prioritu než||což je pravděpodobně důvod, proč jste očekávali, že se váš původní konstrukt bude chovat jakotrue || (echo aaa && echo bbb).To však není případ Bash, ve kterém mají oba operátory stejnou prioritu, a proto Bash analyzuje váš výraz pomocí pravidla asociativity vlevo. Díky Kevinovu komentáři za to, že to přinesl.
-
Mohou také nastat případy, kdy všechny 3 výrazy se vyhodnocují. Pokud první příkaz vrátí nenulový stav ukončení,
||nezkratuje a pokračuje ve vykonání druhého příkazu. Pokud se druhý příkaz vrátí s nulovým stavem ukončení, pak&&nezkratuje a bude proveden třetí příkaz. Díky komentáři Ignacia Vazqueze-Abramse za to, že to přinesl.