2013-11-08 2 views
1

следующего, если/то тест (в Баше):тройной конструкция не эквивалентны, если потом еще

if [ 1 ]; then ls /undef_dummy > /dev/null 2>&1; else echo "else stmt"; fi 

кажется не эквивалентен его троичная версия:

(test 1) && ls /undef_dummy > /dev/null 2>&1 || echo "else stmt" 

Первым будет печатать ничего но второй будет печатать «else stmt».

Это потому, что || оператор в тернарной версии относится к состоянию возврата либо теста , либо команды, выполняемой, если тест проходит. Но обычно мы хотим, чтобы оператор else касался только теста, поэтому здесь небезопасно использовать тернарную версию.

Я прав?

+2

Почему вы называете второй вариант «тройным»? Я не думаю, что 'x && y || z' является тройным в смысле C 'x? y: z' тройной оператор. Это всего лишь состав двух бинарных операторов. И тогда приоритет решает результат. –

+1

вы всегда можете выполнить '(test 1) && (ls ... || true) || echo "else stmt" ' – bobah

+0

Я, вероятно, должен был сказать« порядок оценки »вместо« приоритета ». –

ответ

4

Эта команда:

(test 1) && ls /undef_dummy > /dev/null 2>&1 || echo "else stmt" 

|| проводится оценка, потому что ls возвращается ненулевой код возврата оболочка

Если вы используете эту команду:

test 1 && date || echo "else stmt" 

Тогда он будет печатать но не else stmt

При правильной группировке вашей команды:

test 1 && { ls /undef_dummy > /dev/null 2>&1 || true; } || echo "else stmt" 

не печатает что-нибудь

1

Что вы имеете в виду, как тройная версия фактически эквивалентно:

if (test 1); then 
    if ! ls /undef_dummy > /dev/null 2>&1; then 
    echo "else stmt" 
    fi 
fi 

и довольно отличное от высказывания:

if [ 1 ]; then ls /undef_dummy > /dev/null 2>&1; else echo "else stmt"; fi 
Смежные вопросы