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?我是否正确使用了|
?#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
评论
在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]]是安全的。