Bash 中的三元运算符 (?:)
有没有办法
int a = (b == 5) ? c : d;
使用 Bash 来做这样的事情?
Is there a way to do something like this
int a = (b == 5) ? c : d;
using Bash?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(23)
三元运算符
? :
只是if/then/else
的缩写形式或者
ternary operator
? :
is just a short form ofif/then/else
Or
代码:
Code:
如果条件只是检查变量是否已设置,则还有更简短的形式:
如果
VAR
为,则将VAR
的值分配给a
设置,否则它将为其分配默认值20
——这也可以是表达式的结果。这种方法在技术上称为“参数扩展”。
If the condition is merely checking if a variable is set, there's even a shorter form:
will assign to
a
the value ofVAR
ifVAR
is set, otherwise it will assign it the default value20
-- this can also be a result of an expression.This approach is technically called "Parameter Expansion".
cond &&操作1 ||其他答案中建议的 op2
表达式有一个固有的错误:如果op1
具有非零退出状态,则op2
默默地成为结果;在-e
模式下也不会捕获该错误。因此,只有当op1
永远不会失败时,该表达式才可以安全使用(例如,:
,true
如果是内置函数,或者没有任何变量赋值可能失败的操作(例如除法和操作系统调用))。请注意
""
引号。它们将阻止将所有空白转换为单个空格。如果
$b
等于test
运算符(例如“-z
”),则双方括号(而不是单方括号)可防止错误操作(例如“-z
”;解决方法与[
是[ "x$b" == "xyes" ]
并且它仅适用于字符串比较);他们还提高了报价要求。The
cond && op1 || op2
expression suggested in other answers has an inherent bug: ifop1
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 ifop1
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.Double square brackets as opposed to single ones prevent incorrect operation if
$b
is equal to atest
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.这将避免执行 || 之后的部分意外地当 && 之间的代码和 ||失败了。
This will avoid executing the part after || by accident when the code between && and || fails.
我们可以在 Shell 脚本中使用以下三种方法来实现三元运算符:
更新: 使用下面的可立即运行的示例扩展字符串计算的答案。这是利用上面提到的第二种格式。
We can use following three ways in Shell Scripting for ternary operator :
Update: Extending the answer for string computations with below ready-to-run example. This is making use of second format mentioned above.
let 命令支持大多数需要的基本运算符:
当然,这仅适用于分配变量;它不能执行其他命令。
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:
Just a thought. :)
bash 中的三元条件也有一个非常相似但更简单的语法:
There's also a very similar but simpler syntax for ternary conditionals in bash:
以下似乎适用于我的用例:
示例
并且可以在像这样的脚本中使用:
tern
The following seems to work for my use cases:
Examples
and can be used in a script like so:
tern
这是一个通用的解决方案,它
使用数字比较进行测试
使用字符串比较进行测试
Here's a general solution, that
Test with numerical comparison
Test with String comparison
如果您想要类似的语法,可以使用它
You can use this if you want similar syntax
有些人已经提出了一些不错的替代方案。我想让语法尽可能接近,所以我编写了一个名为
?
的函数。这允许语法:
在这两种情况下,
:
是可选的。所有包含空格的参数、值都必须用引号引起来,因为它使用eval
运行它们。如果
或
子句不是命令,则函数echo
是正确的值。功能
显然如果你想让脚本更短,你可以删除帮助文本。
编辑:我不知道
?
充当文件名中的占位符。它不像*
那样匹配任意数量的字符,而是精确匹配一个字符。因此,如果您的工作目录中有一个单字符文件,bash 将尝试将该文件名作为命令运行。我不知道如何解决这个问题。我想使用命令“?” ...args 可能有效,但是没有骰子。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:
In both cases, the
:
is optional. All arguments that have spaces, the values must be quoted since it runs them witheval
.If the
<then>
or<else>
clauses aren't commands, the functionecho
s the proper value.The function
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 usingcommand "?" ...args
might work but, no dice.最简单的三元
这个示例将确定您是否使用 home
brew
安装bat
如果为 true,您将看到“yes”
如果为 false,您将看到“no”
我添加了
-q
抑制此处的grep
ped 字符串输出,因此您只能看到“yes”或“”
no /code> 和
zsh
Simplest ternary
This example will determine if you used home
brew
to installbat
or not yetIf true you will see "yes"
If false you will see "no"
I added the
-q
to suppress thegrep
ped string output here, so you only see "yes" or "no"Really the pattern you seek is this
Tested with
bash
andzsh
以下是一些选项:
1- 在一行中使用 if then else 是可能的。
2- 编写这样的函数:
像这样使用内部脚本
3- 受案例答案的启发,更灵活的单行用法是:
Here are some options:
1- Use if then else in one line, it is possible.
2- Write a function like this:
use inside script like this
3- Inspired in the case answer, a more flexible and one line use is:
回答:
int a = (b == 5) ? c : d;
只需写:
记住“表达式”相当于$((表达式))
to answer to :
int a = (b == 5) ? c : d;
just write:
remember that " expression " is equivalent to $(( expression ))
另外两个答案
下面是一些思考
bash 整数变量
的方法除了 dutCh、Vladimir 和 ghostdog74 的正确答案,因为这个问题是关于整数和标记bash:
有一种在bash下处理整数的好方法:
该命令的输出行应该是以下之一:
当然,声明变量的整数类型是完成一次:
注意:推荐使用此语法。声明变量的属性,然后赋值,最好单独完成。
题外话:使用字符串作为数学函数:
基于参数扩展和间接
以下答案来自Brad Parks 和 druid62,这是一种方法不限于整数:
b==5
,则ar[b]
是c
并且间接 doc
是50
。ar[除 5 之外的任何值]
为空,因此参数扩展将默认为d
,其中间接给100
。使用数组而不是整数的相同演示
然后
或使用关联数组
然后
Two more answers
Here's some ways of thinking about this
bash integer variables
In addition to, dutCh, Vladimir and ghostdog74's corrects answers and because this question is regarding integer and tagged bash:
There is a nice and proper way to work with integers under bash:
The output line from this command should by one of:
Of course, declaring integer type of variable is to be done once:
Note: This syntax is recommanded. Declaring property of a variable, then assigning a value is better to be done separately.
Digression: Using a string as a math function:
Based on parameter expansion and indirection
Following answers from Brad Parks and druid62, here is a way not limited to integer:
b==5
, thenar[b]
isc
and indirection doc
is50
.ar[any value other than 5]
is empty, so parameter expansion will default tod
, where indirection give100
.Same demo using an array instead of an integer
Then
Or using associative arrays
Then
这很像弗拉基米尔的好答案。如果您的“三元”是“如果 true,字符串,如果 false,空”的情况,那么您可以简单地执行以下操作:
This is much like Vladimir's fine answer. If your "ternary" is a case of "if true, string, if false, empty", then you can simply do:
面向字符串的替代方案,使用数组:
输出:
A string-oriented alternative, that uses an array:
which outputs:
这种方法怎么样:
了解条件语句在 RxJ(即过滤器管道)中如何工作。
是的,这是代码重复,但从我的角度来看,这是更实用的方法。
What about such approach:
See how conditional statements works in the RxJs (i.e. filter pipe).
Yes, it is code duplication but more functional approach from my point of view.
最上面的答案
[[ $b = 5 ]] && a="$c" ||仅当您确定
,否则它将错误地执行&&
之后不会出现错误时才应使用 a="$d"| 之后的部分。 |。
为了解决这个问题,我编写了一个三元函数,它的行为应该如此,它甚至使用
?
和:
运算符:编辑 - 新解决方案
这里是我的新解决方案,不使用
$IFS
也不使用ev(a/i)l
。executeCmds
单独分隔每个命令,除了由于&&
和||
运算符而应跳过的命令之外。每当命令以!
或标志开头时,它就会使用[]
。有两种方法可以向其传递命令:
;
、&&
和||
运营商。NB我发现无法将
&&
和||
运算符作为不带引号的参数传递,因为它们是函数名称和别名中存在非法字符,而且我找不到覆盖 bash 运算符的方法。旧解决方案 - 使用 ev(a/i)l
The top answer
[[ $b = 5 ]] && a="$c" || a="$d"
should only be used if you are certain there will be no error after the&&
, otherwise it will incorrectly excute the part after the||
.To solve that problem I wrote a ternary function that behaves as it should and it even uses the
?
and:
operators:Edit - new solution
Here is my new solution that does not use
$IFS
norev(a/i)l
.executeCmds
separates each command individually, apart from the ones that should be skipped due to the&&
and||
operators. It uses[]
whenever a command starts with!
or a flag.There are two ways to pass commands to it:
;
,&&
, and||
operators.NB I found no way to pass in
&&
and||
operators as parameters unquoted, as they are illegal characters for function names and aliases, and I found no way to override bash operators.Old solution - uses ev(a/i)l