如何在bash中建立条件分配?


70

我正在寻找一种在bash中建立条件分配的方法:

在Java中,它看起来像这样:

int variable= (condition) ? 1 : 0;

Answers:


69

根据乔纳森的评论:

variable=$(( 1 == 1 ? 1 : 0 ))  

编辑:

我修改了最初的答案,该答案只是echo“条件运算符”的值,它实际上并未显示任何赋值。


1
Nit-pick:这不是一个分配-它只是一个条件表达式。但是,variable=$(( 1 == 1 ? 1 : 0 ))只要第一个'='符号之间没有空格,它就可以工作;您可以在此之后省略所有空格,并且也可以使用-但请考虑可读性。
乔纳森·勒夫勒

3
如果将左双括号一直移到最左边,则可以完全自由地移动空格(并放下美元符号)。(( variable = 1 == 1 ? 1 : 0 ))(( variable = (1 == 1) ? 1 : 0 ))但可以说,答案更具有可读性。
丹尼斯·威廉姆森

42
另外,应注意,该运算符仅适用于Bash中的算术运算。
丹尼斯·威廉姆森

13
如果我要设置的变量是字符串怎么办?
Giovanni Botta 2015年

25
这不适用于字符串:echo $(((1 == 1?'hello':'world'))
4aRk Kn1gh7

74

如果您想要一种在Shell脚本中定义默认值的方法,请使用如下代码:

: ${VAR:="default"}

是的,该行以“:”开头。我在shell脚本中使用了它,因此可以覆盖ENV中的变量,也可以使用默认值。

这是相关的,因为这是我最常用的那种逻辑用例。;]


3
这是一项很有价值的技术,但是':='表示法支持的唯一条件是'如果值未设置或为空,则设置为“默认”。bash直接支持问题中更一般的符号。
乔纳森·勒夫勒

2
我完全同意,我给它一个免责声明,因为它与主题无关。
Demosthenex 2010年

3
在相等测试之前省略冒号只是为了使变量未设置,并且如果它为null则不会更改它。
丹尼斯·威廉姆森

有关此答案中以冒号开头和参数扩展的有用说明。
GcL

33
myvar="default" && [[ <some_condition_is_true> ]]  && myvar="non-default"

真实的例子:

DELIM="" && [[ "$APP_ENV_RESOLVED" != "" ]] && DELIM=$INNER_DELIM

该条件也可以是“((... ...))”:

filepath=/proc/drbd && (( $# > 0 )) && filepath=$1

27

除了其他更一般的答案(特别是根据乔纳森的评论和凯文的更一般的答案[也支持字符串]),我想添加以下两种解决方案:


根据条件将变量设置为01

(如问题的示例所示。)

一般形式为

(condition); variable=$?;

其中$variable的结果之中任一01condition可以是任何有效的条件表达式

例如检查变量...

[[ $variableToCheck == "$othervariable, string or number to match" ]]
variable=$?

...或检查文件的存在...

[ -f "$filepath" ]
fileExists=$?

...或检查的数字值$myNumber

(( myNumber >= 1000000000 ))
is_huge_number=$?


该解决方案的优势在于

  • 它支持任意条件表达式,包括字符串
    (Jonathan解决方案的算术表达式不支持)
  • variable被宣布在任何情况下,与格里芬的答案
    [ -z "$variable" ] && variable="defaultValue"
    这将在情况下不管你想nameref后来它(例如,从一个函数中)。


请注意:在Bash中,特殊变量$?始终包含先前执行的语句(或语句块;请参阅man bash的更多详细信息)的退出代码。因此,肯定的结果通常由value表示0,而不是1(请参见下面的评论,感谢Assimilater指出)。因此,如果条件为true(例如[[2 eq 2]]),则$?=0

如果相反,您需要在变量中使用0或1(例如,进行打印或进行数学计算),则需要使用带前导感叹号的布尔求反(如GypsySpellweaver在下面的注释中指出):( ! condition ); variable=$?! ( condition ); variable=$?。(但是,关于发生的事情的可读性可能不太明显。)

乔纳森(Jonathan)的另一种可能的解决方案variable=$(( 1 == 1 ? 1 : 0 ))-但是,它正在创建一个子外壳。

如果要避免创建子平台,保持良好的可读性或具有任意条件,请使用以下解决方案之一。


将变量设置为任意值:

正如在其他大多数答案中所做的那样,它可以进行如下调整:

(condition) \
    && variable=true \
    || variable=false

例如

[[ $variableToCheck == "$othervariable, string or number to match" ]] \
    && variable="$valueIfTrue" \
    || variable="$valueIfFalse"

或在肯定检查中获得1,在失败时获得0(例如在问题的示例中):

[[ $variableToCheck == "$othervariable, string or number to match" ]] \
    && variable=1 \
    || variable=0

(对于最后一个示例,正如上面的注释中已经提到的那样,可以使用前导感叹号通过布尔求反来实现:

[[ ! $variableToCheck == "$othervariable, string or number to match" ]]
variable=$?


该解决方案的优势在于

  • 它可能比Kevin的答案更具可读性,并且
    myvar="default" && [[ <some_condition_is_true> ]] && myvar="non-default"
  • $valueIfTrue有条件评估在需要时
    它会在你做一些无关紧要的情况下
    • 有副作用,像
      • variable=$((i++)), 要么
      • { variable=$1; shift; }
    • 高计算量,例如
      • variable=$(find / -type f -name ListOfFilesWithThisNameOnMySystem)
  • 有点比ghostdog74的答案
    (这不过是伟大的,如果你有多个条件!)
  • 不会像Pierre的回答那样打开子壳
  • 和上面一样:
    • 它支持任意条件表达式,包括字符串
      (Jonathan解决方案的算术表达式不支持)
    • variable被宣布在任何情况下,与格里芬的答案
      [ -z "$variable" ] && variable="defaultValue"
      这将在情况下不管你想nameref后来它(例如,从一个函数中)。

您第一个解决方案的结果使我有些困惑。条件为true的条件的结果为0;如果条件为假,则条件值为1
Assimilater

也许我做错了。我用[ "$1" == "--all" ] ; allperiods=$? ; echo $allperiods
Assimilater

1
@Assimilater,我同意,0和1可能会造成混淆。它源于以下事实:当一切正常时,程序或语句的退出代码通常为0,而对于错误则使用任意代码(通常在1到254之间)。因此executable && executesWhenOk || executesWhenNotOk,在我们的场景中,测试是“可执行的”(准确地说是语句),而特殊变量$?包含最后一条语句的结果代码。希望有助于澄清。
MartinRüegg'16

这很有帮助:)(您可以考虑将其添加到答案中;)))
Assimilater

1
“正常”的布尔逻辑其中程序员适于,的1true0false,可以很容易地在这种情况下与实现NOT !操作者施加到表达。在“表达式”的内部或外部。( ! condition ); variable=$?! ( condition ); variable=$?这样[ ! -f "$filepath" ]; fileExists=$?的程序员习惯于:存在1个文件,而缺少0个文件。
钦德拉巴


8

大起大落对@Demosthenex,尤其是@Dennis威廉姆森的最短和最简单的我见过的解决方案。将其保留为bash,需要为简单的三元分配添加一堆括号啊,六十年代!并在一个示例中将它们放在一起...

echo $BASHRULES;             # not defined
                             # no output
: ${BASHRULES:="SCHOOL"}     # assign the variable
echo $BASHRULES              # check it
SCHOOL                       # correct answer
: ${BASHRULES="FOREVER?"}    # notice the slightly different syntax for the conditional assignment
echo $BASHRULES              # let's see what happened!
SCHOOL                       # unchanged! (it was already defined)

我是很久以前写的..这些天,我可能会对像...这样的解决方案感到更加兴奋。

PLATFORM=iphonesimulator
OTHERSDK=iphone && [[ $PLATFORM=~os ]]      \
                &&     OTHERSDK+=simulator  \
                ||     OTHERSDK+=os

$OTHERSDKiphoneos


2
谢谢@alex grey先生。这是每个人都应该在bash箭袋中使用的极好的语法箭头……对于好奇和/或冒险的人来说,在这里发现它,这种条件赋值也可以与export语句配合使用-您可以将其放在冒号和美元之间,签署声明-y部分,例如: export ${YO_DOGG:="global environment default"}
fish2000

1
您的第二个解决方案实际上代表了我的答案的第二个解决方案,并且仅发布后才添加。一个简短的参考会很好。另请注意,由于iphonesimulator不包含字符串os,因此上述解决方案将以结尾OTHERSDK=iphonesimulator
MartinRüegg'16

我喜欢这个简短的答案。其他一些太长。
MarkHu

5

如果要分配一个值,除非变量为空,请使用以下命令:

[ -z "$variable" ] && variable="defaultValue"

您也可以将其他条件放在 []


3
变量扩展旨在按以下方式进行处理: ${variable:='defaultValue'}
Stphane '16

3

另一种方式

case "$variable" in
  condition ) result=1;;
  *) result=0;;
esac
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.