Linux bash тернарный оператор

Ternary operator (?:) in Bash

@dutCh’s answer shows that bash does have something similar to the «ternary operator» however in bash this is called the «conditional operator» expr?expr:expr (see man bash goto section «Arithmetic Evaluation»). Keep in mind the bash «conditional operator» is tricky and has some gotchas.

Bash does have a ternary operator for integers and it works inside the arithmetic expression ((. )) . See Shell Arithmetic.

Just as @codeforester mentioned, ternary operator works with arithmetic expansion $(( )) and arithmethic evaluation (( )) . See also https://mywiki.wooledge.org/ArithmeticExpression .

23 Answers 23

ternary operator ? : is just short form of if/else

case "$b" in 5) a=$c ;; *) a=$d ;; esac 

Note that the = operator tests for string equality, not numeric equality (i.e. [[ 05 = 5 ]] is false). If you want numeric comparison, use -eq instead.

The cond && op1 || op2 construct has an inherent bug: if op1 has nonzero exit status for whatever reason, the result will silently become op2 . if cond; then op1; else op2; fi is one line too and doesn’t have that defect.

this is better than the others. the point about the tertiary operator is that it’s an operator, hence it’s proper context is in an expression, hence it must return a value.

This is the most concise way. Be aware that if the part with echo «$c» is an aliased, multi-lined command (like echo 1; echo 2 ), you should enclose it in parentheses.

This will also capture any output of the tested command, too (yes, in this particular case, we «know» it doesn’t produce any).

This chain of operators only behaves like a ternary operator if you are positive that the command after && won’t have a non-zero exit status. Otherwise, a && b || c will «unexpectedly» run c if a succeeds but b fails.

If the condition is merely checking if a variable is set, there’s even a shorter form:

will assign to a the value of VAR if VAR is set, otherwise it will assign it the default value 20 — this can also be a result of an expression.

This approach is technically called «Parameter Expansion».

Not what the OP wanted, but just wanted to say thanks for teaching me something new today that fit my scenario perfectly ^_^

@KenWilliams Actually there is a syntax like that, it uses a second type of parameter expansion, :+ . You can do $:-no> . if VAR is set & non-null, this will expand to yes and if VAR is unset or null it expands to no .

if [[ $b -eq 5 ]]; then a="$c"; else a="$d"; fi 

The cond && op1 || op2 expression suggested in other answers has an inherent bug: if op1 has a nonzero exit status, op2 silently becomes the result; the error will also not be caught in -e mode. So, that expression is only safe to use if op1 can never fail (e.g., : , true if a builtin, or variable assignment without any operations that can fail (like division and OS calls)).

Note the «» quotes. They will prevent translation of all whitespace into single spaces.

Читайте также:  Linux memory use command

Double square brackets as opposed to single ones prevent incorrect operation if $b is equal to a test operator (e.g. » -z «; a workaround with [ is [ «x$b» == «xyes» ] and it only works for string comparison); they also lift the requirement for quoting.

Great point! I would just like to add that this is exactly the kind of sneaky bug that ShellCheck finds for you. In this case, the relevant wiki page.

(( a = b==5 ? c : d )) # string + numeric 

This is good for numeric comparisons and assignments, but it will give unpredictable results if you use it for string comparisons and assignments. (( )) treats any/all strings as 0

This will avoid executing the part after || by accident when the code between && and || fails.

This will still not catch the error in -e mode: (set -o errexit; [ 5 == 5 ] && < false; true; echo "success"; >|| echo «failure»; echo $?; echo «further on»;) -> success 0 further on

@TomHale No. && and || by definition apply to the entire command before them. So, if you have two commands before it (regardless of how they are combined), you cannot apply it to only to one of them and not the other. You can emulate if / then / else logic with flag variables, but why bother if there’s if / then / else proper?

We can use following three ways in Shell Scripting for ternary operator :

 [ $numVar == numVal ] && resVar="Yop" || resVar="Nop" Or resVar=$([ $numVar == numVal ] && echo "Yop" || echo "Nop") Or (( numVar == numVal ? (resVar=1) : (resVar=0) )) 

Update: Extending the answer for string computations with below ready-to-run example. This is making use of second format mentioned above.

$ strVar='abc';resVar=$([[ $strVar == 'abc' ]] && echo "Yop" || echo "Nop");echo $resVar Yop $ strVar='aaa';resVar=$([[ $strVar == 'abc' ]] && echo "Yop" || echo "Nop");echo $resVar Nop 

This is actually (the first and second specifically, of these three examples) the most appropriate answer to this question IMHO.

Each of the suggested ways has limitations/caveats which are not explained. So using this answer is dangerous.

The let command supports most of the basic operators one would need:

Naturally, this works only for assigning variables; it cannot execute other commands.

Here is another option where you only have to specify the variable you’re assigning once, and it doesn’t matter whether what your assigning is a string or a number:

VARIABLE=`[ test ] && echo VALUE_A || echo VALUE_B` 

A major downside: it will also capture the stdout of [ test ] . So the construct is only safe to use if you «know» that the command doesn’t output anything to stdout.

Also the same as stackoverflow.com/questions/3953645/ternary-operator-in-bash/… plus the need to quote and escape quotes inside. The space-tolerant version will look like VARIABLE=»`[ test ] && echo \»VALUE_A\» || echo \»VALUE_B\»`» .

There’s also a very similar but simpler syntax for ternary conditionals in bash:

The following seems to work for my use cases:

Examples

$ tern 1 YES NO YES $ tern 0 YES NO NO $ tern 52 YES NO YES $ tern 52 YES NO 52 NO 

and can be used in a script like so:

RESULT=$(tern 1 YES NO) echo "The result is $RESULT" 

tern

#!/usr/bin/env bash function show_help() < ME=$(basename "$0") IT=$(cat if [ "$1" = "help" ] || [ "$1" = '?' ] || [ "$1" = "--help" ] || [ "$1" = "h" ]; then show_help fi if [ -z "$3" ] then show_help fi # Set a default value for what is "false" -> 0 FALSE_VALUE=$ function main < if [ "$1" == "$FALSE_VALUE" ] || [ "$1" = '' ]; then echo $3 exit; fi; echo $2 >main "$1" "$2" "$3" 

hey @太極者無極而生 — that’s the name of the bash script — save that «tern» section above to a file named «tern», then run chmod 700 tern in the same folder. Now you’ll have a tern command in your terminal

Читайте также:  Linux command error log

Here’s a general solution, that

  • works with string tests as well
  • feels rather like an expression
  • avoids any subtle side effects when the condition fails

Test with numerical comparison

a=$(if [ "$b" -eq 5 ]; then echo "$c"; else echo "$d"; fi) 

Test with String comparison

a=$(if [ "$b" = "5" ]; then echo "$c"; else echo "$d"; fi) 

This solution has the same defect ivan_pozdeev describes above where for this solution, echo «false» may occur when ping is successful, but where, for some reason, however unlikely, the echo «true» part returns a non-zero exit status (see ShellCheck SC2015). To echo «false» only when ping fails, regardless of echo «true» ’s exit status, move the first grouping brace < to the head: < (ping -c1 localhost&>/dev/null) && echo «true»; > || < echo "false"; >.

You can use this if you want similar syntax

This works only with integers. You can write it more simply as a=$(((b==5) ? : c : d)) — $((. )) is needed only when we want to assign the result of the arithmetic to another variable.

Some people have already presented some nice alternatives. I wanted to get the syntax as close as possible, so I wrote a function named ? .

This allows for the syntax:

[[ $x -eq 1 ]]; ? ./script1 : ./script2 # or ? '[[ $x -eq 1 ]]' ./script1 : ./script2 

In both cases, the : is optional. All arguments that have spaces, the values must be quoted since it runs them with eval .

If the or clauses aren’t commands, the function echo s the proper value.

The function

?() < local lastRet=$? if [[ $1 == --help || $1 == -? ]]; then echo $'\e[37;1mUsage:\e[0m ? [] [:] If \e[37;1m\e[0m and/or \e[37;1m\e[0m are not valid commands, then their values are printed to stdOut, otherwise they are executed. If \e[37;1m\e[0m is not specified, evaluates the return code ($?) of the previous statement. \e[37;1mExamples:\e[0m myVar=$(? "[[ $x -eq 1 ]] foo bar) \e[32;2m# myVar is set to "foo" if x is 1, else it is set to "bar"\e[0m ? "[[ $x = *foo* ]] "cat hello.txt" : "cat goodbye.txt" \e[32;2m# runs cat on "hello.txt" if x contains the word "foo", else runs cat on # "goodbye.txt"\e[0m ? "[[ $x -eq 1 ]] "./script1" "./script2"; ? "Succeeded!" "Failed :(" \e[32;2m# If x = 1, runs script1, else script2. If the run script succeeds, prints # "Succeeded!", else prints "failed".\e[0m' return elif ! [[ $# -eq 2 || $# -eq 3 || $# -eq 4 && $3 == ':' ]]; then 1>&2 echo $'\e[37;1m?\e[0m requires 2 to 4 arguments \e[37;1mUsage\e[0m: ? [] [:] Run \e[37;1m? --help\e[0m for more details' return 1 fi local cmd if [[ $# -eq 2 || $# -eq 3 && $2 == ':' ]]; then cmd="[[ $lastRet -eq 0 ]]" else cmd="$1" shift fi if [[ $2 == ':' ]]; then eval "set -- '$1' '$3'" fi local result=$(eval "$cmd" && echo "$1" || echo "$2") if command -v $ &> /dev/null; then eval "$" else echo "$" fi > 

Obviously if you want the script to be shorter, you can remove the help text.

Читайте также:  Как запустить гта на линукс

EDIT: I was unaware that ? acts as a placeholder character in a file name. Rather than matching any number of characters like * , it matches exactly one character. So, if you have a one-character file in your working directory, bash will try to run the filename as a command. I’m not sure how to get around this. I thought using command «?» . args might work but, no dice.

Источник

How to Use Ternary Operator (?:) in Bash

The Ternary Operator, also known as the conditional operator, is an important feature of Bash Linux that allows developers to perform conditional operations in a single line of code. It allows users to write conditional statements in a more concise and readable way. This article will discuss in detail the ternary operator and how a user can utilize it in bash scripting using the following outline.

How a Ternary Operator Works?

The syntax of the Ternary Operator in Bash Linux is as follows:

(condition) ? expression1 : expression2

A condition (a Boolean expression) evaluates to true, and expression1 is executed; otherwise, expression2 is executed.

Examples of Ternary Operator

This section will discuss a few examples of ternary operators for better understanding.

Example 1: Comparing Two Variables

If a user wants to compare two variables using a ternary operator, then it can be done by following the below bash script:

#!/bin/bash a=10 b=20 max=$((a>b ? a : b)) echo $max

Code Explanation

  • Two variables, a and b, are being compared using the Ternary Operator.
  • If a is greater than b, a is assigned to the max. Otherwise, b is assigned to the max.

Code Execution

The output of the code can be seen by executing the bash script below:

The variable ‘a’ has a value of 10 whereas the variable ‘b’ has a value of 20 which is greater than variable a, so its value is printed on the terminal.

Example 2: Comparing Three Variables

Similarly, a user can compare more than two variables as well using the ternary operator as shown below:

#!/bin/bash a=10 b=20 c=30 max=$(((a>b)?(a>c?a:c):(b>c?b:c))) echo $max

Code Explanation

  • Three variables, a, b, and c are being compared having different values.
  • If a is greater than b and c, a is assigned to the max.
  • If b is greater than a and c, b is assigned to the max.
  • Otherwise, c is assigned to the max. In this case, the output will be 30.

Code Execution

The code output can be seen by executing the bash script below:

Variable ‘a’ has a value of 10, variable ‘b’ has a value of 20, and variable ‘c’ has a value of 30. A variable c has the greatest value among the three, so its value will be printed on the terminal.

Conclusion

Ternary Operator is a powerful feature of Bash Linux that allows users to perform conditional operations in a single line of code. It can be an alternative option for an If else statement, and the code written in it will be short. Detailed information regarding the ternary operator has been provided in this article, along with examples.

Источник

Оцените статью
Adblock
detector