这个问题是我先前提出的问题的后遗症。这个站点上的用户帮助我确定了如何编写对字符串值进行迭代的bash for循环。例如,假设循环控制变量fname遍历字符串"a.txt" "b.txt" "c.txt"。我想对echo“是!”当fname的值为"a.txt""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

我获得了输出:

a.txt
否!
b.txt
否!
c.txt
是!

为什么当if的值为fname时,"a.txt"语句显然产生true?我是否正确使用了|

评论

在bash中,“或”运算符为“ ||” (C风格)。

您也可以在同一[]中使用-o。

@Thor我更喜欢||并在-o上将[]与-o分开以实现可移植性,这仅仅是因为[无法保证支持4个以上的参数。当然,如果目标语言是bash,则任何人都不应使用[,因为bash的[[在许多方面都比较出色。

@ jw013谢谢。这是否意味着如果[[“ $ fname” =“ a.txt”]] ||我应该使用[[“” $ fname“ =” c.txt“]],而不是如果[[$ fname” =“ a.txt”] || [“ $ fname” =“ c.txt”]?

@Andrew这是正确的,如果正如您已经声明的那样将shebang声明为bash。 [[的一个优点是它不进行单词拆分(特殊情况),因此[[$ unquoted_var = string]]是安全的。

#1 楼

如果您要说OR使用双管道(||)。

if [ "$fname" = "a.txt" ] || [ "$fname" = "c.txt" ]


(使用|的原始OP代码只是将左侧的输出通过管道传递到右侧,就像普通管道一样。)



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

要使用OR,要进行||

是否使用[[[test((均视情况而定。在所有情况下都首选其中之一是错误的。有时[是正确的,而[[是错误的。但这不是问题所在。 OP询问为什么|不起作用。答案是因为应该改为||

评论


此外,||不执行标准逻辑“或”-它会短路,并且仅在第一个命令失败时才运行第二个命令。

– holdenweb
16-12-12在19:33



@holdenweb我敢肯定,大多数现代优化语言的工作方式都是相同的。如果第一个条件为true,则无需花费CPU周期来评估OR的第二个条件。

– bahamat
16 Dec 12'在20:50

我以为bash喜欢==,但在看到此答案后,我决定查找它。显然,“它可以使用,但不是标准的”。我想如果您好奇的话,会把这个放在这里给别人看:stackoverflow.com/a/2237103

–哈珀维尔
18/09/17在15:55

这也是测试手册页所建议的

–cdosborn
19年4月21日在18:13

您也可以使用双括号测试-如果[[“ $ fname” =“ a.txt”]] || [[“ $ fname” =“ c.txt”]](如果您希望或需要具有与[[]]关联的额外功能)。

–HankCa
19年4月24日在5:45

#2 楼

可接受的答案很好,但是由于您正在使用bash,因此我将添加bash解决方案:
if [[ "$fname" == "a.txt" || "$fname" == "c.txt" ]]; then

这在bash参考手册3.2.4.2有条件的构造中记录了

expression1 && expression2

如果expression1和expression2均为真,则为真。

expression1 || expression2

如果expression1或expression2为真,则为真。

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


评论


+1同意这是更好的答案(与“已接受”答案相比)。细心的读者应注意||。 (或&&)位于条件内,在这种情况下,该条件必须使用[[...]]而不是[...](即不是shell的“或” /“和”)。我只补充说[[...]]不仅更有用,支持更多选项(例如||,&&,<,>),而且比旧的[...]更“安全”;也支持单括号语法中的旧-a和-o,并且按预期,运算符“ and”优先于“ or”。 tldp.org/LDP/abs/html/testconstructs.html#DBLBRACKETS

–迈克尔
20年5月19日在23:30



我认为@AnandShanbhag的答案比这更好。为什么要花费神经元来打扰单括号或双括号?来吧,让您的读者受益:使用测试

–马西莫
20年6月3日在19:49

对于&&运算符,这是真的吗? “如果expression1的值足以确定整个条件表达式的返回值,则&&和||运算符不会评估expression2。”我了解||案例,但有人知道您不需要评估expression2的&&案例吗?从逻辑上讲这似乎不太可能,但是我可能会丢失或误解某些东西。

– jbobbins
20 Sep 25'4:05



@jbobbins:如果expression1为false,则无需评估expression2。

– jesse_b
20-09-25在11:20

哇,真令人尴尬...我想我的大脑被锁定在真实模式下了。 ;(也许是时候退休了:D

– jbobbins
20 Sep 25 '15:10

#3 楼

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

if test "$fname" = "a.txt" || test "$fname" = "c.txt"


评论


从根本上讲,这与接受的答案(和一些评论)相同,但字符更多,(恕我直言)可读性较低。

– G-Man说“恢复莫妮卡”
20 May 15 '21:20

比起括号,阅读测试更容易。为什么要使代码变得比必要的更加神秘?

–马西莫
20 May 27 '15:12

#4 楼

您可以使用或调节这样的条件

 if [ "$fname" = "a.txt" -o "$fname" = "c.txt" ]


评论


是的,可以,但是在POSIX标准中将-o用作“或”标记为过时,对于-and则将-a用作“和”标记。新代码不应使用-o或-a。

– Kusalananda♦
20-1-4在14:19



它也导致代码不可靠,因为当给定超过4个参数(在[和]旁边)时,[命令并不总是能够正确解析其参数。例如尝试使用fname ='!'与bash shell的内置[

–StéphaneChazelas
20年7月20日在12:24