Ответ @ dutCh показывает, что у bashнего есть нечто похожее на «троичный оператор», однако bashэто называется «условный оператор» expr?expr:expr(см. man bashраздел «Арифметическая оценка»). Имейте в виду, что bash«условный оператор» хитрый и имеет некоторые ошибки.
Тревор Бойд Смит
У Bash есть троичный оператор для целых чисел, и он работает внутри арифметического выражения ((...)). Смотрите Арифметику Shell .
codeforester
1
Как уже упоминалось @codeforester, троичный оператор работает с арифметическим расширением $(( ))и арифметическим вычислением (( )). Смотрите также https://mywiki.wooledge.org/ArithmeticExpression.
Кай
Ответы:
490
троичный оператор ? :это просто краткая формаif/else
Обратите внимание, что =оператор проверяет равенство строк, а не числовое равенство (т. [[ 05 = 5 ]]Е. False). Если вы хотите числовое сравнение, используйте -eqвместо этого.
Гордон Дэвиссон
10
Это скорее краткая форма дляif/then/else
vol7ron
15
Это гениальный способ использовать поведение короткого замыкания для получения эффекта троичного оператора :) :) :)
mtk
6
почему [[и]]? это работает так же, как это: [$ b = 5] && a = "$ c" || a = "$ d"
kdubs
83
У cond && op1 || op2конструкции есть свойственная ошибка: если op1по какой-либо причине имеет ненулевой статус выхода, результатом будет молчаливый результат op2. if cond; then op1; else op2; fiтоже одна строка и не имеет этого дефекта.
это лучше, чем другие ... Суть третичного оператора в том, что это оператор, поэтому его надлежащий контекст находится в выражении, поэтому он должен возвращать значение.
Ник Ферри
2
Это самый лаконичный способ. Помните, что если часть с echo "$c"является командой с псевдонимами, состоящей из нескольких строк (например echo 1; echo 2), вы должны заключить ее в скобки.
Мэтт
2
Это также будет захватывать любые выходные данные протестированной команды (да, в данном конкретном случае мы «знаем», что она не выдает).
ivan_pozdeev
8
Эта цепочка операторов ведет себя только как троичный оператор, если вы уверены, что команда после &&не будет иметь ненулевой статус выхода. В противном случае a && b || c «неожиданно» запустится, cесли aполучится, но bне получится .
chepner
155
Если условие просто проверяет, установлена ли переменная, есть даже более короткая форма:
a=${VAR:-20}
присвоит aзначение VARif VAR, в противном случае он назначит ему значение по умолчанию 20- это также может быть результатом выражения.
Как отмечает Алекс в комментарии, этот подход технически называется «Расширение параметров».
В случае передачи строкового параметра с дефисами, я должен был использовать кавычки: a=${1:-'my-hyphenated-text'}
saranicole
1
ссылка для ленивых - есть дополнительные операторы, чем просто замена ( :-)
Джастин Вробел
10
@JustinWrobel - к сожалению, нет синтаксиса, как ${VAR:-yes:-no}.
Кен Уильямс
76
if["$b"-eq 5];then a="$c";else a="$d";fi
cond && op1 || op2Выражение предлагается в других ответах имеет присущую ошибку: если op1имеет ненулевой статус завершения, op2молча становится результатом; ошибка также не будет поймана в -eрежиме. Таким образом, это выражение только безопасно использовать , если op1не может потерпеть неудачу (например, :, trueесли встроены ным , или присваивания значения переменных без каких - либо операций , которые могут не (как разделение и вызовы ОС)).
Обратите внимание на ""цитаты. Первая пара предотвратит синтаксическую ошибку, если $bона пуста или имеет пробел. Другие будут препятствовать переводу всех пробелов в отдельные пробелы.
Я также видел префикс, который, как мне кажется, [ "x$b" -eq "x" ]использовался специально для проверки пустой строки. Мне нравится использовать синтаксисы, используемые zsh («РАСШИРЕНИЕ ПАРАМЕТРОВ» на странице руководства zshexpn), но я не очень разбираюсь в их переносимости.
Это хорошо для числовых сравнений и назначений, но даст непредсказуемые результаты, если вы будете использовать его для сравнения и присвоения строк .... (( ))обрабатывает любые / все строки как0
Peter.O
3
Это также может быть написано:a=$(( b==5 ? c : d ))
Joeytwiddle
33
[ $b ==5]&&{ a=$c; true;}|| a=$d
Это позволит избежать выполнения части после || случайно, когда код между && и || выходит из строя.
@ivan_pozdeev Есть ли способ использовать &&.. ||и все же поймать неудачную команду между ними?
Том Хейл
2
@ TomHale Нет. &&И ||по определению относится ко всей команде перед ними. Таким образом, если перед вами две команды (независимо от того, как они объединены), вы не можете применить их только к одной из них, а не к другой. Вы можете эмулировать if/ then/ elseлогику с помощью флаговых переменных, но зачем беспокоиться, если if/ then/ elseправильно?
ivan_pozdeev
14
Команда let поддерживает большинство основных операторов, которые могут понадобиться:
let a=b==5?c:d;
Естественно, это работает только для назначения переменных; он не может выполнять другие команды.
он в точности эквивалентен ((...)), поэтому он действителен только для арифметических выражений
drAlberT
13
Вот еще один вариант, где вам нужно только указать переменную, которую вы назначаете один раз, и не имеет значения, является ли ваше назначение строкой или числом:
VARIABLE=`[ test ] && echo VALUE_A || echo VALUE_B`
Главный недостаток: он также захватит стандартный поток [ test ]. Таким образом, конструкция безопасна только в том случае, если вы «знаете», что команда ничего не выводит в стандартный вывод.
Очень объяснительно. Очень полный Очень многословно. Три вещи, которые мне нравятся. ;-)
Джесси Чисхолм
2
является ternчастью Bash? У Мака, похоже, его нет
неполярность
4
эй @ 太極 者 無極 而 生 - это имя скрипта bash - сохраните этот раздел «tern» выше в файл с именем «tern», а затем запустите chmod 700 ternв той же папке. Теперь у вас будет ternкоманда в вашем терминале
Брэд Паркс
8
Мы можем использовать следующие три способа в сценариях оболочки для троичного оператора:
Это работает только с целыми числами. Вы можете написать это более просто как a=$(((b==5) ? : c : d))- $((...))нужно только тогда, когда мы хотим присвоить результат арифметики другой переменной.
Codeforester
2
Вот несколько вариантов:
1 - Используйте, если затем еще в одной строке, это возможно.
# Once upon a time, there was an 'iif' function in MS VB ...function iif(){# Echoes $2 if 1,banana,true,etc and $3 if false,null,0,''case $1 in''|false|FALSE|null|NULL|0) echo $3;;*) echo $2;;esac}
использовать внутри скрипта, как это
result=`iif "$expr" 'yes' 'no'`# or even interpolating:
result=`iif "$expr" "positive" "negative, because $1 is not true"`
3- Вдохновленный ответом на конкретный вопрос, более гибкое и однозначное использование:
case"$expr"in''|false|FALSE|null|NULL|0) echo "no...$expr";;*) echo "yep $expr";;esac# Expression can be something like:
expr=`expr "$var1" '>' "$var2"`
Это очень похоже на хороший ответ Владимира . Если ваш «троичный» является случаем «если истина, строка, если ложь, пусто», то вы можете просто сделать:
$ c="it was five"
$ b=3
$ a="$([[ $b -eq 5 ]] && echo "$c")"
$ echo $a
$ b=5
$ a="$([[ $b -eq 5 ]] && echo "$c")"
$ echo $a
it was five
bash
него есть нечто похожее на «троичный оператор», однакоbash
это называется «условный оператор»expr?expr:expr
(см.man bash
раздел «Арифметическая оценка»). Имейте в виду, чтоbash
«условный оператор» хитрый и имеет некоторые ошибки.((...))
. Смотрите Арифметику Shell .$(( ))
и арифметическим вычислением(( ))
. Смотрите такжеhttps://mywiki.wooledge.org/ArithmeticExpression
.Ответы:
троичный оператор
? :
это просто краткая формаif/else
Или
источник
=
оператор проверяет равенство строк, а не числовое равенство (т.[[ 05 = 5 ]]
Е. False). Если вы хотите числовое сравнение, используйте-eq
вместо этого.if/then/else
cond && op1 || op2
конструкции есть свойственная ошибка: еслиop1
по какой-либо причине имеет ненулевой статус выхода, результатом будет молчаливый результатop2
.if cond; then op1; else op2; fi
тоже одна строка и не имеет этого дефекта.Код:
источник
echo "$c"
является командой с псевдонимами, состоящей из нескольких строк (напримерecho 1; echo 2
), вы должны заключить ее в скобки.&&
не будет иметь ненулевой статус выхода. В противном случаеa && b || c
«неожиданно» запустится,c
еслиa
получится, ноb
не получится .Если условие просто проверяет, установлена ли переменная, есть даже более короткая форма:
присвоит
a
значениеVAR
ifVAR
, в противном случае он назначит ему значение по умолчанию20
- это также может быть результатом выражения.Как отмечает Алекс в комментарии, этот подход технически называется «Расширение параметров».
источник
a=${1:-'my-hyphenated-text'}
:-
)${VAR:-yes:-no}
.cond && op1 || op2
Выражение предлагается в других ответах имеет присущую ошибку: еслиop1
имеет ненулевой статус завершения,op2
молча становится результатом; ошибка также не будет поймана в-e
режиме. Таким образом, это выражение только безопасно использовать , еслиop1
не может потерпеть неудачу (например,:
,true
если встроены ным , или присваивания значения переменных без каких - либо операций , которые могут не (как разделение и вызовы ОС)).Обратите внимание на
""
цитаты. Первая пара предотвратит синтаксическую ошибку, если$b
она пуста или имеет пробел. Другие будут препятствовать переводу всех пробелов в отдельные пробелы.источник
[ "x$b" -eq "x" ]
использовался специально для проверки пустой строки. Мне нравится использовать синтаксисы, используемые zsh («РАСШИРЕНИЕ ПАРАМЕТРОВ» на странице руководства zshexpn), но я не очень разбираюсь в их переносимости.источник
(( ))
обрабатывает любые / все строки как0
a=$(( b==5 ? c : d ))
Это позволит избежать выполнения части после || случайно, когда код между && и || выходит из строя.
источник
-e
(set -o errexit; [ 5 == 5 ] && { false; true; echo "success"; } || echo "failure"; echo $?; echo "further on";)
success 0 further on
:
вместоtrue
сохраненияexec
внешней программы.&&
..||
и все же поймать неудачную команду между ними?&&
И||
по определению относится ко всей команде перед ними. Таким образом, если перед вами две команды (независимо от того, как они объединены), вы не можете применить их только к одной из них, а не к другой. Вы можете эмулироватьif
/then
/else
логику с помощью флаговых переменных, но зачем беспокоиться, еслиif
/then
/else
правильно?Команда let поддерживает большинство основных операторов, которые могут понадобиться:
Естественно, это работает только для назначения переменных; он не может выполнять другие команды.
источник
Вот еще один вариант, где вам нужно только указать переменную, которую вы назначаете один раз, и не имеет значения, является ли ваше назначение строкой или числом:
Просто мысль. :)
источник
[ test ]
. Таким образом, конструкция безопасна только в том случае, если вы «знаете», что команда ничего не выводит в стандартный вывод.VARIABLE="`[ test ] && echo \"VALUE_A\" || echo \"VALUE_B\"`"
.Следующее, кажется, работает для моих случаев использования:
Примеры
и может быть использован в сценарии так:
крачка
источник
tern
частью Bash? У Мака, похоже, его нетchmod 700 tern
в той же папке. Теперь у вас будетtern
команда в вашем терминалеМы можем использовать следующие три способа в сценариях оболочки для троичного оператора:
источник
Существует также очень похожий синтаксис для троичных условных выражений в bash:
К сожалению, это работает только с числами - насколько я знаю.
источник
источник
Вы можете использовать это, если вы хотите подобный синтаксис
источник
a=$(((b==5) ? : c : d))
-$((...))
нужно только тогда, когда мы хотим присвоить результат арифметики другой переменной.Вот несколько вариантов:
1 - Используйте, если затем еще в одной строке, это возможно.
2- Напишите такую функцию:
использовать внутри скрипта, как это
3- Вдохновленный ответом на конкретный вопрос, более гибкое и однозначное использование:
источник
Вот общее решение, которое
Тест с числовым сравнением
a = $(if [ "$b" -eq 5 ]; then echo "$c"; else echo "$d"; fi)
Тест со сравнением строк
a = $(if [ "$b" = "5" ]; then echo "$c"; else echo "$d"; fi)
источник
ответить на:
int a = (b == 5) ? c : d;
просто пиши:
помните, что «выражение» эквивалентно $ ((выражение))
источник
Это очень похоже на хороший ответ Владимира . Если ваш «троичный» является случаем «если истина, строка, если ложь, пусто», то вы можете просто сделать:
источник
Строково-ориентированная альтернатива, использующая массив:
какие выводы:
источник