我刚刚在ksh脚本中找到了以下代码:
if [ "${file_id}" = "0" ] || [ "${file_id}" = "100" ] || "${file_id}" = "100" ]
then
# Do some stuff
fi
请特别注意,在第三个[
之前缺少${file_id}
。
我很高兴这不是非常令人愉快的语法,即使没有错误,[[ … ]]
通常比ksh中的[ … ]
更可取。
但是,此代码完全按照需要运行,ksh -n
完全不反对上述代码。为什么上述失败?
答案 0 :(得分:2)
if [ "${file_id}" = "0" ] || [ "${file_id}" = "100" ] || "${file_id}" = "100" ]
此命令从左到右切换。如果此命令发现file_id
的值为0
,则它不会检查下一个条件,因为这些条件是使用or
运算符分隔的。如果第一和第二条件都不满足,那么它将尝试检查第三个条件并且它将失败。
file_id=1000
if [ "${file_id}" = "0" ] || [ "${file_id}" = "100" ] || "${file_id}" = "100" ]
then
echo "Exicuted for file_id=$file_id"
fi
ksh: 1000: not found.
答案 1 :(得分:1)
我的第一个猜测是,只要第一个表达式的计算结果为true,这将对大多数(或所有) Bourne-type shell执行正确。这是预期的行为,因为&&
和||
实际上使执行短路:即在a || b
中,如果a为真,则不评估b部分。
请考虑以下事项:
% for sh in ash bash ksh zsh;do
printf 'running %s with id %d\n\n' "$sh" 0
"$sh" -c 'file_id=0;[ "${file_id}" -eq 0 ] || oops'
done
running ash with id 0
running bash with id 0
running ksh with id 0
running zsh with id 0
% for sh in ash bash ksh zsh;do
printf 'running %s with id %d\n\n' "$sh" 1
"$sh" -c 'file_id=1;[ "${file_id}" -eq 0 ] || oops'
done
running ash with id 1
ash: oops: not found
running bash with id 1
bash: oops: command not found
running ksh with id 1
ksh: oops: not found
running zsh with id 1
zsh:1: command not found: oops
还有更多,你不能在短路表达式的右侧键入任何你想要的东西,因为解析器将在执行之前尝试解析整行(即错误放置的元字符会导致错误)
% ksh -c 'id=0; [ "$id" -eq 0 ] || )'
ksh: syntax error: ')' unexpected
另请注意,只要延迟执行命令(内置或外部), shell无法知道它是否有效。相反,shell保留字语法和元字符的位置在分析时是已知的:
% ksh -c 'type [ [[;id=0; [ "$id" -eq 0 ] || [[ '
ksh: syntax error: unexpected EOF
% ksh -c 'type [ [[;id=0; [ "$id" -eq 0 ] || [ '
[ is a shell builtin
[[ is a reserved word