ksh 坏[… ] 语法不会导致错误

发布于 2024-12-11 04:07:21 字数 397 浏览 1 评论 0原文

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

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

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

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

然而,这段代码完全按照预期运行,并且 ksh -n 根本不反对上述内容。为什么上面的方法没有失败呢?

I've just found the following code in a ksh script:

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

Note, in particular, the missing [ before the third ${file_id}.

I'm happy that this isn't very pleasant syntax, even without that error, and that [[ … ]] is generally preferable to [ … ] in ksh.

However, this code runs entirely as desired, and ksh -n doesn't object to the above at all. Why doesn't the above fail?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

弃爱 2024-12-18 04:07:21

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.

if [ "${file_id}" = "0" ] || [ "${file_id}" = "100" ] || "${file_id}" = "100" ]

This command exicuted from Left to Right. If this command found the value of file_id is 0 then it will not check for the next conditions because, these conditions are separated with the or operator. If both 1st and 2nd conditions will not satisfied then it will try to check for the 3rd condition and it will be failed.

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.
红尘作伴 2024-12-18 04:07:21

我的第一个猜测是,只要第一个表达式的计算结果为 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

还有更多,您不能在短路表达式的右侧输入您想要的任何内容,因为解析器将在执行之前尝试解析整行(即放错位置的元字符 em> 将导致错误)

% 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

My first guess is that this will execute correctly with most (or all) Bourne-type shells as long as the first expression evaluates true. This is expected behavior, as the && and || actually short-circuit the execution: i.e. In a || b, the b part is not evaluated if a is true.

Consider the following:

% 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

There is more though, you cannot type whatever you want on the right side of the short-circuiting expression, because the parser will try to parse the entire line, before executing it (i.e. a misplaced metacharacter will cause an error)

% ksh -c 'id=0; [ "$id" -eq 0 ] || )' 
ksh: syntax error: ')' unexpected

Notice also that as long as the command (builtin or external) execution is deferred,
the shell couldn't know if it's valid or not. On the contrary, the shell reserved words syntax and the positions of the metacharacters are known in parse-time:

% 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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文