ksh bad [...]语法不会导致错误

时间:2011-10-20 12:53:11

标签: syntax ksh

我刚刚在ksh脚本中找到了以下代码:

  if [ "${file_id}" = "0" ] || [ "${file_id}" = "100" ] || "${file_id}" = "100" ]
  then
    # Do some stuff
  fi

请特别注意,在第三个[之前缺少${file_id}

我很高兴这不是非常令人愉快的语法,即使没有错误,[[ … ]]通常比ksh中的[ … ]更可取。

但是,此代码完全按照需要运行,ksh -n完全不反对上述代码。为什么上述失败?

2 个答案:

答案 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