转自 ttp://blog.csdn.net/security134/article/details/6742156

最近学习SHELL编程 这篇文章很好很重要。有些东西不能想当然。同时不是表面看起来那么简单。以为自己懂了。其实差的还远

Cuibtoy发布于 2008-8-28 http://www.linuxdiyf.com/viewarticle.php?id=105505

我打赌正在看这篇文章的你, 超过99%的可能性你对这个问题的理解是错的. 或者至少是有偏差的.

我深信这是一种教育法上的广泛错误, 那就是告诉大家说:

if [ condition ]
then
...
fi

这是bash中条件语句的"语法".

任何人, 或者说几乎任何人, 都会在这种描述下自然地认为: [ 和 ] 是这种语法结构本身的一部分, 并且,
老老实实地在自己的脚本中总是这样使用if 语句, 如果你总是在判断字符串是否相等, 或文件的各种属性, 这么做倒是没错,
只不过你可能会这样犯错:(下文都假设$1内容为-a)

if ["$1" = "-a" ]

if [ "$1 = "-a"]

毕竟, 很多其它语言中, 特殊符号如()、{}做分隔符时, 可以与被分隔内容亲密无间. 而bash会来答复你的这种写法:

[-a: command not found
bash: [: missing `]'

我相信, 以上这种心理模型造成的失败后果十分严重, bash的错误信息显示出它内部并不这样看待if 条件语句的结构.

上面的模型同样不能解释下面的合法bash 命令:

[ "$1" = "-a" ]

仅仅这本身就是一个合法的命令, 没有if、then、fi这些东西,当然, 下面这样的也合法

[ "$1" = "-a" ] && echo yes

你如何解释这些烂事? 当然你可以自圆其说地不断对上面的if进行补充, 呃, [ .. ] 这种结构就是这么特别, 你必需在[之后有至少一个空格,
并且在]之前也至少有一个空格, 同时[..] 结构还可以单独出现, 就象上面这样, 另外... 这样的解释简直是自欺欺人,
我敢保证企图对自己这样解释的人根本自己就在怀疑这种说法, 因为你根本不知道这个结构还有其它什么怪诞诡秘之处何时会突然跳出来让你大吃一惊.
我承认,我自己也曾经经历过这样的想法.

为了彻底批判这种错误概念, 容我再举一例:

if ps ax | grep oracle > /dev/null 2>&1 ; then
...
fi

首先, 这是合法的, 它的目的是想知道进程列表中有没有与oracle相关的东西, 当然, 如果你够牛, 就能看出这种做法有另外的问题. 但这不是我想说的重点.

我想说的是, 你前面被教导的这种if 语句的语法模型, 如何解释这个, [ 与 ] 又不见了, 并且还出现了管道, 普通的管道我们都见过, 但它能安全地出现在if 语句中吗, 并且, 让你感觉熟悉和安全的[ 和 ]又不见了.

好吧, 拨乱的部分至此为止, 如果你想获得一个关于bash中if结构的正确的健康的环保的知识, 就打起精神往下看:

1. 首先, [ 在bash中没有特殊地位, 它是一个命令, 就跟cat, ls, grep一样让你感到熟悉的命令. 它不是关键字,虽然它的更出色的胞弟"[["是

echo [

你就得到 [, 不信就试试, bash不会报告任何错误! 但这不说明它不是关键字, echo if你也能得到if

所以, 请再试:

which [
以及
ls -l $(which [)

2. 然后, if 的真正模型是:

if COMMANDS; then COMMANDS; [ elif COMMANDS; then COMMANDS; ]... [ else COMMANDS; ] fi

其实, bash中的help if就给了你正确的答案, 但我不知道什么原因无数人就是忽略了它, 而非常多的bash教学资料中都采用了本文开头提出的那种模型来告诉你关于if 结构的事.

注意: [ "$1" = "-a" ] 只一个命令, [ 是命令名!, "$1"是第一个参数, =是第二个参数, "-a"是第三个,
]是第4个. 是[这个命令, 而不是bash本身在报怨 [ "$1" = "-a"] 这样的结构造成的错误, 因为[这个命令对它的参数有所期望,
它期望最后一个参数是 ], 而你用"-a"] 这种连写的形式, 它得到的就只有3个参数: $1, = 和 -a].

这也解释了这样的错误:
["$1" = "-a" ]

bash解释器得到了这样的一个命令行:
[-a = "-a" ]

当然, 它认为 [-a 是命令名部分, 而你的系统中没有这个命令, 所以会报告说:
[-a: command not found

3. 其次, bash中有一个builtin的 [命令, 通常你使用[执行的都是这个内置的命令, 目的是效率. 启动一个进程的代价太高.

试试
type [
命令

转 关于shell中if 语法结构的广泛误解的更多相关文章

  1. Java初认识--Java中的语法结构

    Java中的语法结构(程序流程控制) Java的语法结构有四种: 1.顺序结构. 顺序结构很简单,就是按顺序执行,输出就可以了. 2.判断结构. 判断结构的一个代表性的语句是if:if语句有三种格式体 ...

  2. shell中的控制流结构

    shell中的控制流结构 1.if...then..else..fi语句 2.case语句 3.for循环 4.until 语句 5.while循环 6.break控制 7.continue 控制 1 ...

  3. (八)shell中的循环结构

    1.for循环(1)要求:能看懂.能改即可.不要求能够完全不参考写出来.因为毕竟嵌入式并不需要完全重新手写shell,系统管理员(服务器运维人员,应用层系统级管理开发的才需要完全掌握shell) 这里 ...

  4. shell中的语法(1)

    反引号 命令替换.将命令的输出放在命令行的任意位置. eg. [root@gam ~]# echo The Data is `date` The Data is Fri Nov 18 10:13:56 ...

  5. shell中switch语法

    转载: https://blog.csdn.net/love__coder/article/details/7262160

  6. ANTLR4权威指南 - 第6章 尝试一些实际中的语法

    第6章 尝试一些实际中的语法 在前一章,我们学习了通用词法结构和语法结构,并学习了如何用ANTLR的语法来表述这些结构.现在,是时候把我们学到的这些用来构建一些现实世界中的语法了.我们的主要目标是,怎 ...

  7. shell中select、case的使用

    case和select结构在技术上说并不是循环, 因为它们并不对可执行代码块进行迭代. 但是和循环相似的是, 它们也依靠在代码块顶部或底部的条件判断来决定程序的分支. select   select结 ...

  8. shell中的(),{}几种语法用法

    转自:https://www.cnblogs.com/HKUI/p/6423918.html 查看脚本语法是否有错误:bash -n modify_suffix.sh跟踪执行sh -x modify_ ...

  9. centos shell脚本编程1 正则 shell脚本结构 read命令 date命令的用法 shell中的逻辑判断 if 判断文件、目录属性 shell数组简单用法 $( ) 和${ } 和$(( )) 与 sh -n sh -x sh -v 第三十五节课

    centos   shell脚本编程1 正则  shell脚本结构  read命令  date命令的用法  shell中的逻辑判断  if 判断文件.目录属性  shell数组简单用法 $( ) 和$ ...

随机推荐

  1. 17、Semantic-UI之分页插件

      在很多的前端开发框架中都会有提供分页插件,但是分页插件的使用如果手动编写还是比较复杂的.使用Semantic-UI中的分页插件更加简单方便.分页插件的使用必须要和后台结合. 示例:定义分页插件 & ...

  2. 从源码角度看Transaction以及如何手工接管Transaction实现高度的自定义化

    一:transaction CUD: 在一个transaction中... transaction: start add.... delete... update... transaction: co ...

  3. Arduino I2C + AC24C32 EEPROM

    主要特性 AC24C32是Atmel的两线制串行EEPROM芯片,根据工作电压的不同,有-2.7.-1.8两种类型.主要特性有: 工作范围:-2.7类型范围4.5~5.5V,-1.8类型1.8~5.5 ...

  4. How can i use iptables on centos 7 or fedora?

    http://stackoverflow.com/questions/24756240/how-can-i-use-iptables-on-centos-7 # sudo service iptabl ...

  5. mvn -v提示Permission denied

    解决办法: 增加权限 chmod a+x  /usr/local/apache-maven-3.5.2/bin/mvn 解释: (a:所有用户  +:增加权限   x:执行权限)

  6. Windowsform datagridview选中向父窗口传值

    Datagridview mouseclick事件 private void dataGridView1_MouseClick(object sender, MouseEventArgs e) { i ...

  7. Qt自动填写表单并点击按钮,包括调用js方法

    本篇博客参阅了很多其他大牛的文章,具体找不到了,还望包涵>_< 因为其他博客大都是只有主要代码,对于像我这种菜鸟,根本摸不着头脑,以此想总结一下,帮助新手尽快实现功能... 主要是调用了C ...

  8. HDU - 6215 2017 ACM/ICPC Asia Regional Qingdao Online J - Brute Force Sorting

    Brute Force Sorting Time Limit: 1 Sec  Memory Limit: 128 MB 题目连接 http://acm.hdu.edu.cn/showproblem.p ...

  9. Binder学习笔记(一)

    网上看了很多关于binder的文章,但我还是想把自己的心路历程记录下来,有些是跟着别人的脚步领略险峻风景,有些则是自己只身探入代码深处打捞出的收获.我不确定是否全部融会贯通,更担心一两个月后会完全不记 ...

  10. linux命令之磁盘与文件系统管理命令(上)

    1.fdisk:磁盘分区工具 该命令是linux下常用的磁盘分区工具,但是只能给小于2TB的磁盘划分分区. 常用参数为-l,显示所有磁盘分区的信息. 示例: 1)显示磁盘分区列表 [root@boxi ...