zoukankan      html  css  js  c++  java
  • 关于bash中if语法结构的广泛误解(转)

    转自:
    http://blog.chinaunix.net/u/8681/showart.php?id=1145851

    我打赌正在看这篇文章的你, 超过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 [
    命令


    几乎所有的书都会讲呀? [ ... ] 是调用test命令的特殊形式, 参考下面的命令。
    $help [
    [: [ arg... ]
    This is a synonym for the "test" builtin, but the last
    argument must be a literal `]', to match the opening `['.
    $man test
    NAME
    test - check file types and compare values

    SYNOPSIS
    test EXPRESSION
    test

    [ EXPRESSION ]
    [ ]
    [ OPTION

    DESCRIPTIO...
  • 相关阅读:
    MySQL 数据库 查询语句的基本操作,单表查询,多表查询
    MySQL数据库 外键,级联, 修改表的操作
    MySQL数据库 存储引擎,创建表完整的语法,字段类型,约束条件
    MySQL数据库 介绍,安装,基本操作
    python GIL全局解释器锁,多线程多进程效率比较,进程池,协程,TCP服务端实现协程
    子进程回收资源两种方式,僵尸进程与孤儿进程,守护进程,进程间数据隔离,进程互斥锁,队列,IPC机制,线程,守护线程,线程local作用,线程池,回调函数add_done_callback,TCP服务端实现并发
    并发编程 操作系统发展史,多道技术,进程,同步与异步,阻塞与非阻塞,进程的三种状态,创建进程的两种方式
    网络编程 UDP协议 TCP局域网客户端与服务端上传下载电影示例
    网络编程 TCP协议:三次握手,四次挥手,反馈机制 socket套接字通信 粘包问题与解决方法
    k8s 常用命令
  • 原文地址:https://www.cnblogs.com/end/p/2695432.html
Copyright © 2011-2022 走看看