Привет. Я устал от сложностей написания Bash курса и решил отдохнуть и написать статью.

Сегодня поговорим об очень редко используемом и на мой взгляд, абсолютно ненужном и неадекватно работающем операторе bash. И сравним его с классикой.

Представляю Вашему вниманию тернарный (троичный) оператор.

В мануале он выглядит так:

expr1 ? expr2 : expr3
Tagd Tagd
Tagd Tagd
Bash Master
Задать вопрос
Работает оператор так: если expr1 истина, то результат expr2, иначе expr3.

Для исследования я написал небольшую тестовую программу

#!/bin/bash
declare -i c=033 #27
declare -i d=044 #36
declare -i k=0 #counter

function wait2sec(){
  sleep 2
  echo $1
}

SECONDS=0
a=$((1 == 2?$(wait2sec c):$(wait2sec d))) #0
echo $((k++)) sec=$SECONDS a=$a

SECONDS=0
((a=1==2?$(wait2sec c):$(wait2sec d))) #1
echo $((k++)) sec=$SECONDS a=$a

SECONDS=0
a=$((1==2?$(wait2sec c):$(wait2sec d))) #2
echo $((k++)) sec=$SECONDS a=$a

SECONDS=0
[[ 1 == 2 ]] && a=$(wait2sec c) || a=$(wait2sec d) #3
echo $((k++)) sec=$SECONDS a=$a

SECONDS=0
[[ 1==2 ]] && a=$(wait2sec c) || a=$(wait2sec d) #4
echo $((k++)) sec=$SECONDS a=$a

####### result #############
# 0 sec=4 a=36
# 1 sec=4 a=36
# 2 sec=4 a=36
# 3 sec=2 a=d
# 4 sec=2 a=c

Функция wait2sec ждет 2 секунды и печатает первый параметр. Дальше идут пять как бы одинаковых блоков.

1 == 2 - expr1 (false)
wait2sec c - expr2
wait2sec d - expr3

Анализируем результаты:

  1. переменные d и с описаны как целые, но начинаются с 0, поэтому bash интерпретирует их как восьмеричные.

  2. Тернарный оператор может использоваться только внутри арифметической подсистемы ((…)), в которой переменные допускается извлекать(получать значение) без знака $, поэтому c и d интерпретируются как переменные.

  3. У тернарного оператора допустима даже “упоротая” форма (блок 1)

  4. В математической подсистеме при сравнении пробелы вокруг знака сравнения не влияют на результат.

  5. В блоке 4 допущена ошибка (нет пробелов вокруг знака сравнения, поэтому 1==2 - интерпретируется не как результат сравнения, а как не пустая строка, поэтому результат (истина) неверный. Такие ошибки очень трудно отлаживать.

  6. В отличие от классического, башевского, сравнения при использовании тернарного оператора expr2 и expr3 вычисляются вне зависимости от условия. Об этом говорит удвоенное время выполнения блока.