在 bash 脚本中,在“if”语句中使用条件“or”

And*_*rew 329 bash shell-script

这个问题是我之前问题的续集。该站点上的用户帮助我确定了如何编写一个for遍历字符串值的 bash循环。例如,假设循环控制变量fname遍历字符串"a.txt" "b.txt" "c.txt"。我想echo“是的!” 何时fname具有值"a.txt"or "c.txt",并且echo“不!” 除此以外。我尝试了以下 bash shell 脚本:

#!/bin/bash

for fname in "a.txt" "b.txt" "c.txt"
do
  echo $fname
  if [ "$fname" = "a.txt" ] | [ "$fname" = "c.txt" ]; then
    echo "yes!"
  else
    echo "no!"
  fi
done
Run Code Online (Sandbox Code Playgroud)

我获得输出:

一个.txt

不!

b.txt

不!

文件

是的!

为什么该if语句在fname具有 value时显然会产生 true "a.txt"?我用|错了吗?

bah*_*mat 548

如果你想说OR使用双管(||)。

if [ "$fname" = "a.txt" ] || [ "$fname" = "c.txt" ]
Run Code Online (Sandbox Code Playgroud)

(使用的原始 OP 代码|只是将左侧的输出通过管道传输到右侧,与任何普通管道的工作方式相同。)


经过多年的评论和误解,请允许我澄清一下。

要做到OR你使用||

无论您使用[[[test((一切都取决于你需要在个案基础的情况下什么。说在所有情况下都首选其中之一是错误的。有时候[是对的,[[也是错的。但这不是问题所在。OP问为什么|不起作用。答案是因为它应该是||

  • @holdenweb 我很确定大多数现代优化语言的工作方式相同。如果第一个条件评估为真,则无需花费 CPU 周期来评估“OR”的第二个条件。 (30认同)
  • 此外,`||` 不执行标准逻辑“或” - 它会短路,并且仅当第一个命令失败时才运行第二个命令。 (9认同)
  • 您还可以使用双括号测试 - `if [[ "$fname" = "a.txt" ]] || [[ "$fname" = "c.txt" ]]`(如果你想要或需要拥有与 `[[ ]]` 相关的额外功能)。 (8认同)
  • 我以为 bash 喜欢 `==` 但看到这个答案后,我决定查一下。显然,“它可以使用,但不是标准的”。如果你好奇的话,我想我会把它放在这里给其他人:/sf/answers/156597241/ (7认同)
  • 我不同意你的说法,但无论如何这都不是重点。问题是为什么“|”不起作用。答案是因为它应该是`||`。使用“test”与“[”与问题完全无关。 (3认同)
  • @Massimo 由于 `[` 与 `test` 是一回事,所以它实际上是相同的答案。 (2认同)
  • 我也完全不同意马西莫的观点,“测试”非常不直观,而且括号更容易阅读。在编程语言之间切换时也更容易。 (2认同)

jes*_*e_b 138

接受的答案很好,但由于您使用的是 bash,我将添加 bash 解决方案:

if [[ "$fname" == "a.txt" || "$fname" == "c.txt" ]]; then
Run Code Online (Sandbox Code Playgroud)

这记录在 bash 参考手册3.2.4.2 Conditional Constructs

表达式 1 && 表达式 2

如果表达式 1 和表达式 2 都为真,则为真。

表达式 1 || 表达式2

如果表达式 1 或表达式 2 为真,则为真。

&& 和 || 如果 expression1 的值足以确定整个条件表达式的返回值,则运算符不会计算 expression2。

  • +1 同意这是更好的答案(与“已接受”的答案相比)。细心的读者应该注意`||`(或`&&`)是_inside_条件,在这种情况下,它必须使用`[[...]]` 而不是`[...]`(即,它不是外壳的“或”/“和”)。我只会补充一点,`[[ ... ]]` 不仅更有用,支持更多选项(例如`||`、`&&`、`<`、`>`),而且比旧的“更安全” `[...]`; 旧的`-a` 和`-o` 也支持单括号语法,正如预期的那样,运算符“and”优先于“or”。http://www.tldp.org/LDP/abs/html/testconstructs.html#DBLBRACKETS (4认同)
  • 哇,太尴尬了……我猜我的大脑被锁定在真实模式了。;(也许是时候退休了:D (4认同)
  • @jbobbins:如果表达式1为假,则无需计算表达式2。 (2认同)

小智 7

您还可以像这样使用 OR 条件

if test "$fname" = "a.txt" || test "$fname" = "c.txt"
Run Code Online (Sandbox Code Playgroud)

  • 这基本上与接受的答案(以及一些评论)相同,但字符更多并且(恕我直言)可读性较差。 (7认同)
  • 马西莫,您在每个答案下都回复说您认为“测试”更方便,但没有人对这些评论进行投票。你需要多少提示?你可能认为你的方式是最好的,但我认为大多数人不同意。对不起 :) (4认同)
  • 那是你的主观意见。我的观点是括号更容易阅读。我们的观点都不是“正确的”,只是说说而已。 (3认同)