La réponse de @ dutCh montre qu'il basha quelque chose de similaire à "l'opérateur ternaire", mais dans bashce cas, il est appelé "opérateur conditionnel" expr?expr:expr(voir la man bashsection "Évaluation arithmétique"). Gardez à l'esprit que l ' bash"opérateur conditionnel" est délicat et comporte quelques accrochages.
Trevor Boyd Smith
Bash a un opérateur ternaire pour les entiers et il fonctionne à l'intérieur de l'expression arithmétique ((...)). Voir Shell Arithmetic .
codeforester
1
Tout comme @codeforester l'a mentionné, l'opérateur ternaire travaille avec l'expansion $(( ))arithmétique et l'évaluation arithmétique (( )). Voir aussi https://mywiki.wooledge.org/ArithmeticExpression.
Kai
Réponses:
490
opérateur ternaire ? :est juste une forme abrégée deif/else
Notez que l' =opérateur teste l'égalité des chaînes, pas l'égalité numérique (c'est [[ 05 = 5 ]]-à- dire est faux). Si vous souhaitez une comparaison numérique, utilisez -eqplutôt.
Gordon Davisson
10
C'est plus une forme courte pourif/then/else
vol7ron
15
C'est une manière géniale d'utiliser le comportement de court-circuit pour obtenir un effet d'opérateur ternaire :) :) :)
mtk
6
pourquoi le [[et]]? cela fonctionne aussi bien comme ceci: [$ b = 5] && a = "$ c" || a = "$ d"
kdubs
83
La cond && op1 || op2construction a un bug inhérent: si le op1statut de sortie est différent de zéro pour une raison quelconque, le résultat deviendra silencieusement op2. if cond; then op1; else op2; fiest aussi une ligne et n'a pas ce défaut.
c'est mieux que les autres ... le point sur l'opérateur tertiaire est que c'est un opérateur, donc son contexte est dans une expression, donc il doit retourner une valeur.
nic ferrier
2
C'est la manière la plus concise. Sachez que si la pièce avec echo "$c"est une commande aliasée à plusieurs lignes (comme echo 1; echo 2), vous devez la mettre entre parenthèses.
Matt
2
Cela capturera également toute sortie de la commande testée (oui, dans ce cas particulier, nous "savons" qu'elle n'en produit aucune).
ivan_pozdeev
8
Cette chaîne d'opérateurs ne se comporte comme un opérateur ternaire que si vous êtes certain que la commande suivante &&n'aura pas un état de sortie non nul. Sinon, a && b || c s'exécutera "de manière inattendue" en ccas de asuccès mais d' béchec.
chepner
155
Si la condition vérifie simplement si une variable est définie, il existe même une forme plus courte:
a=${VAR:-20}
affectera à ala valeur de VARif VARest définie, sinon il lui attribuera la valeur par défaut 20- cela peut également être le résultat d'une expression.
Comme le note Alex dans le commentaire, cette approche est appelée techniquement "Expansion des paramètres".
@JustinWrobel - malheureusement pas de syntaxe comme ${VAR:-yes:-no}.
Ken Williams
76
if["$b"-eq 5];then a="$c";else a="$d";fi
L' cond && op1 || op2expression suggérée dans d'autres réponses a un bogue inhérent: si elle op1a un statut de sortie différent de zéro, op2devient silencieusement le résultat; l'erreur ne sera pas non plus détectée en -emode. Donc, cette expression n'est sûre que si elle op1ne peut jamais échouer (par exemple :,true si une commande interne, ou l' affectation des variables sans aucune opération qui peut échouer (comme la division et les appels OS)).
Notez les ""citations. La première paire empêchera une erreur de syntaxe si elle $best vide ou a des espaces. D'autres empêcheront la traduction de tous les espaces en espaces simples.
J'ai également vu le préfixe, je crois [ "x$b" -eq "x" ]utilisé pour tester spécifiquement la chaîne vide. J'aime utiliser les syntaxes utilisées par zsh ('PARAMETER EXPANSION' dans la page de manuel zshexpn) mais je ne connais pas grand-chose à leur portabilité.
C'est bon pour les comparaisons et les affectations numériques , mais cela donnera des résultats imprévisibles si vous l'utilisez pour les comparaisons et les affectations de chaînes .... (( ))traite toutes les chaînes comme0
Peter.O
3
Cela peut aussi être écrit:a=$(( b==5 ? c : d ))
joeytwiddle
33
[ $b ==5]&&{ a=$c; true;}|| a=$d
Cela évitera d'exécuter la pièce après || par accident lorsque le code entre && et || échoue.
Cela n'attrapera toujours pas l'erreur en -emode: (set -o errexit; [ 5 == 5 ] && { false; true; echo "success"; } || echo "failure"; echo $?; echo "further on";)->success 0 further on
ivan_pozdeev
2
Utilisez le :bulit-in au lieu d' trueenregistrer execun programme externe.
Tom Hale
@ivan_pozdeev Existe-t-il un moyen d'utiliser &&.. ||et d'attraper toujours une commande ayant échoué entre eux?
Tom Hale
2
@TomHale No. &&et, ||par définition, s'appliquent à la commande entière avant eux. Donc, si vous avez deux commandes devant lui (quelle que soit la façon dont elles sont combinées), vous ne pouvez pas l'appliquer uniquement à l'une d'entre elles et non à l'autre. Vous pouvez émuler if/ then/ elselogic avec des variables de drapeau, mais pourquoi s'embêter s'il y a if/ then/ elsebon?
ivan_pozdeev
14
La commande let prend en charge la plupart des opérateurs de base dont on aurait besoin:
let a=b==5?c:d;
Naturellement, cela ne fonctionne que pour affecter des variables; il ne peut pas exécuter d'autres commandes.
il est exactement équivalent à ((...)), il n'est donc valable que pour les expressions arithmétiques
drAlberT
13
Voici une autre option où vous n'avez qu'à spécifier la variable que vous attribuez une fois, et peu importe si votre affectation est une chaîne ou un nombre:
VARIABLE=`[ test ] && echo VALUE_A || echo VALUE_B`
Un inconvénient majeur: il captera également la sortie standard de [ test ]. Ainsi, la construction n'est sûre que si vous "savez" que la commande ne renvoie rien à stdout.
ivan_pozdeev
Également le même que stackoverflow.com/questions/3953645/ternary-operator-in-bash/… plus la nécessité de citer et d'échapper les citations à l'intérieur. La version à tolérance d'espace ressemblera VARIABLE="`[ test ] && echo \"VALUE_A\" || echo \"VALUE_B\"`".
ivan_pozdeev
8
Les éléments suivants semblent fonctionner pour mes cas d'utilisation:
Exemples
$ tern 1 YES NO
YES
$ tern 0 YES NO
NO
$ tern 52 YES NO
YES
$ tern 52 YES NO 52
NO
et peut être utilisé dans un script comme celui-ci:
RESULT=$(tern 1 YES NO)
echo "The result is $RESULT"
sterne
function show_help(){
echo ""
echo "usage: BOOLEAN VALUE_IF_TRUE VALUE_IF_FALSE {FALSE_VALUE}"
echo ""
echo "e.g. "
echo ""
echo "tern 1 YES NO => YES"
echo "tern 0 YES NO => NO"
echo "tern "" YES NO => NO"
echo "tern "ANY STRING THAT ISNT 1" YES NO => NO"
echo "ME=$(tern 0 YES NO) => ME contains NO"
echo ""
exit
}if["$1"=="help"]then
show_help
fiif[-z "$3"]then
show_help
fi# Set a default value for what is "false" -> 0
FALSE_VALUE=${4:-0}function main
{if["$1"=="$FALSE_VALUE"];then
echo $3
exit;fi;
echo $2
}
main "$1""$2""$3"
Très explicatif. Très complet. Très verbeux. Trois choses que j'aime. ;-)
Jesse Chisholm
2
fait ternpartie de Bash? Mac ne semble pas l'avoir
non
4
hey @ 太極 者 無極 而 生 - c'est le nom du script bash - enregistrez la section "tern" ci-dessus dans un fichier nommé "tern", puis exécutez-le chmod 700 terndans le même dossier. Maintenant, vous aurez une terncommande dans votre terminal
Brad Parks
8
Nous pouvons utiliser les trois méthodes suivantes dans Shell Scripting pour l'opérateur ternaire:
Cela ne fonctionne qu'avec des entiers. Vous pouvez l'écrire plus simplement car a=$(((b==5) ? : c : d))- $((...))n'est nécessaire que lorsque nous voulons affecter le résultat de l'arithmétique à une autre variable.
codeforester
2
Voici quelques options:
1- Utiliser si alors autrement sur une seule ligne, c'est possible.
# 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}
utiliser un script intérieur comme celui-ci
result=`iif "$expr" 'yes' 'no'`# or even interpolating:
result=`iif "$expr" "positive" "negative, because $1 is not true"`
3- Inspiré de la réponse au cas, une utilisation plus flexible et sur une seule ligne est:
case"$expr"in''|false|FALSE|null|NULL|0) echo "no...$expr";;*) echo "yep $expr";;esac# Expression can be something like:
expr=`expr "$var1" '>' "$var2"`
Cela ressemble beaucoup à la bonne réponse de Vladimir . Si votre "ternaire" est un cas de "si vrai, chaîne, si faux, vide", alors vous pouvez simplement faire:
$ 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
a quelque chose de similaire à "l'opérateur ternaire", mais dansbash
ce cas, il est appelé "opérateur conditionnel"expr?expr:expr
(voir laman bash
section "Évaluation arithmétique"). Gardez à l'esprit que l 'bash
"opérateur conditionnel" est délicat et comporte quelques accrochages.((...))
. Voir Shell Arithmetic .$(( ))
arithmétique et l'évaluation arithmétique(( ))
. Voir aussihttps://mywiki.wooledge.org/ArithmeticExpression
.Réponses:
opérateur ternaire
? :
est juste une forme abrégée deif/else
Ou
la source
=
opérateur teste l'égalité des chaînes, pas l'égalité numérique (c'est[[ 05 = 5 ]]
-à- dire est faux). Si vous souhaitez une comparaison numérique, utilisez-eq
plutôt.if/then/else
cond && op1 || op2
construction a un bug inhérent: si leop1
statut de sortie est différent de zéro pour une raison quelconque, le résultat deviendra silencieusementop2
.if cond; then op1; else op2; fi
est aussi une ligne et n'a pas ce défaut.Code:
la source
echo "$c"
est une commande aliasée à plusieurs lignes (commeecho 1; echo 2
), vous devez la mettre entre parenthèses.&&
n'aura pas un état de sortie non nul. Sinon,a && b || c
s'exécutera "de manière inattendue" enc
cas dea
succès mais d'b
échec.Si la condition vérifie simplement si une variable est définie, il existe même une forme plus courte:
affectera à
a
la valeur deVAR
ifVAR
est définie, sinon il lui attribuera la valeur par défaut20
- cela peut également être le résultat d'une expression.Comme le note Alex dans le commentaire, cette approche est appelée techniquement "Expansion des paramètres".
la source
a=${1:-'my-hyphenated-text'}
:-
)${VAR:-yes:-no}
.L'
cond && op1 || op2
expression suggérée dans d'autres réponses a un bogue inhérent: si elleop1
a un statut de sortie différent de zéro,op2
devient silencieusement le résultat; l'erreur ne sera pas non plus détectée en-e
mode. Donc, cette expression n'est sûre que si elleop1
ne peut jamais échouer (par exemple:
,true
si une commande interne, ou l' affectation des variables sans aucune opération qui peut échouer (comme la division et les appels OS)).Notez les
""
citations. La première paire empêchera une erreur de syntaxe si elle$b
est vide ou a des espaces. D'autres empêcheront la traduction de tous les espaces en espaces simples.la source
[ "x$b" -eq "x" ]
utilisé pour tester spécifiquement la chaîne vide. J'aime utiliser les syntaxes utilisées par zsh ('PARAMETER EXPANSION' dans la page de manuel zshexpn) mais je ne connais pas grand-chose à leur portabilité.la source
(( ))
traite toutes les chaînes comme0
a=$(( b==5 ? c : d ))
Cela évitera d'exécuter la pièce après || par accident lorsque le code entre && et || échoue.
la source
-e
mode:(set -o errexit; [ 5 == 5 ] && { false; true; echo "success"; } || echo "failure"; echo $?; echo "further on";)
->success 0 further on
:
bulit-in au lieu d'true
enregistrerexec
un programme externe.&&
..||
et d'attraper toujours une commande ayant échoué entre eux?&&
et,||
par définition, s'appliquent à la commande entière avant eux. Donc, si vous avez deux commandes devant lui (quelle que soit la façon dont elles sont combinées), vous ne pouvez pas l'appliquer uniquement à l'une d'entre elles et non à l'autre. Vous pouvez émulerif
/then
/else
logic avec des variables de drapeau, mais pourquoi s'embêter s'il y aif
/then
/else
bon?La commande let prend en charge la plupart des opérateurs de base dont on aurait besoin:
Naturellement, cela ne fonctionne que pour affecter des variables; il ne peut pas exécuter d'autres commandes.
la source
Voici une autre option où vous n'avez qu'à spécifier la variable que vous attribuez une fois, et peu importe si votre affectation est une chaîne ou un nombre:
Juste une pensée. :)
la source
[ test ]
. Ainsi, la construction n'est sûre que si vous "savez" que la commande ne renvoie rien à stdout.VARIABLE="`[ test ] && echo \"VALUE_A\" || echo \"VALUE_B\"`"
.Les éléments suivants semblent fonctionner pour mes cas d'utilisation:
Exemples
et peut être utilisé dans un script comme celui-ci:
sterne
la source
tern
partie de Bash? Mac ne semble pas l'avoirchmod 700 tern
dans le même dossier. Maintenant, vous aurez unetern
commande dans votre terminalNous pouvons utiliser les trois méthodes suivantes dans Shell Scripting pour l'opérateur ternaire:
la source
Il existe également une syntaxe très similaire pour les conditions ternaires en bash:
Malheureusement, cela ne fonctionne qu'avec des chiffres - pour autant que je sache.
la source
la source
Vous pouvez l'utiliser si vous souhaitez une syntaxe similaire
la source
a=$(((b==5) ? : c : d))
-$((...))
n'est nécessaire que lorsque nous voulons affecter le résultat de l'arithmétique à une autre variable.Voici quelques options:
1- Utiliser si alors autrement sur une seule ligne, c'est possible.
2- Écrivez une fonction comme celle-ci:
utiliser un script intérieur comme celui-ci
3- Inspiré de la réponse au cas, une utilisation plus flexible et sur une seule ligne est:
la source
Voici une solution générale,
Test avec comparaison numérique
a = $(if [ "$b" -eq 5 ]; then echo "$c"; else echo "$d"; fi)
Test avec comparaison de chaînes
a = $(if [ "$b" = "5" ]; then echo "$c"; else echo "$d"; fi)
la source
répondre à:
int a = (b == 5) ? c : d;
Ecrivez:
rappelez-vous que "expression" est équivalente à $ ((expression))
la source
Cela ressemble beaucoup à la bonne réponse de Vladimir . Si votre "ternaire" est un cas de "si vrai, chaîne, si faux, vide", alors vous pouvez simplement faire:
la source
Une alternative orientée chaîne, qui utilise un tableau:
qui génère:
la source