Shell 简明教程 快速上手

作为一个 Java 程序员,Go 爱好者,自然免不了天天和 Linux 打交道,也曾经写过一点点 shell 脚本,但是对那个反人类的语法深感厌恶,空格不对都不行。无奈项目需要一定要用 shell 来实现一个工具,学习的过程总是不那么顺风的,不过搞完之后也觉得没那么讨厌了。整理一下几天所得,希望能让一个从没写过 shell 但是还挺熟悉 Linux 的可以立马完成一个可用的脚本。

  1. 执行顺序

脚本顺序执行,原来怎么敲命令的就怎么写

  1. 变量赋值

    # 变量赋值时等号两边不能有空格
    # 单引号是固定字符串
    pa='string'
    
    # 双引号可包含变量
    pb="ps is ${pa}"
    
    # 接受命令返回
    pc=`ls -alh`
    
  2. 数组及其遍历

    arr=(aa bb cc dd ff)
    # 通过下标访问
    for ((i=0; i<5; i++))
    do
        echo "$i: ${arr[$i]}"
    done
    
    # 遍历访问
    for s in ${arr[@]}
    do
    echo "  $s"
    done
    
    # 空格分隔的字符串也能遍历,但是不能像上面的方式一样用下标访问元素
    arr2='a1 a2 a3 a4 a5'
    for s in ${arr2}
    do
    echo ${s}
    done
    
  3. 条件判断

    # shell 脚本都是指令,if 的语句一定要注意空格
    # 第一种写法,下面输出 ok
    if [[ 10 -gt 3 ]]; then echo ok; else echo no; fi
    
    # 第二种, ** 注意(): 下面输出 ok
    if [ 2 > 3 ]; then 
        echo ok
    fi
    
    # 第三种, 下面输出 no
    if [[ 2 > 3 ]]
    then 
        echo ok
    else 
        echo no
    fi
    
  4. 定义函数

    res=0
    echo $res
    
    add() {
        ((res = $1 + $2))
    }
    add 12 13
    echo $res
    
  5. $? 说明

    # $?接受的是上一条命令执行后的返回值
    ls /home
    
    # 下面的输出是 0
    echo $?
    
    testReurn() {
        return 8
    }
    testReurn
    
    # 下面的输出是 8 
    echo $?
    
  6. 字符串操作

    a='stringA'
    b='stringB'
    
    # 判断是否相等,下面输出 no
    if [[ $a == $b ]]; then echo yes; else echo no; fi
    
    # 字符串拼接, 下面输出 yes
    if [[ 'stringAstringB' == "${a}${b}" ]]; then echo yes; fi
    
    # 取字符串长度, 下面输出 7
    echo ${#a}
    
    # 截取字符串, 下面输出  string, ing
    echo "${a:0:6}, ${a:3:3}"
    
    # 判断两个字符串是否有相同前缀, 下面输出 yes
    if [[ ${a:0:5} == ${b:0:5} ]]; then echo yes; else echo no; fi
    
    # 字符串切分为数组, IFS 变量指定分隔符, 分隔符前后空格会被略去
    IFS=, read -r -a arr <<< 'a,b  ,c, d,g e,   ss'
    for str in ${arr[@]}; do echo "'${str}'"; done
    
  7. 文件和目录判断

    if [[ -f $filename ]]; then
      echo "$filename 是一个文件"
    elif [[ -d $filename ]]; then
      echo "$filename 是一个目录"
    elif [[ -p $filename ]]; then
      echo "$filename 是一个管道文件"
    elif [[ -S $filename ]]; then
      echo "$filename 是一个 sokcet 文件"
    elif [[ -b $filename ]]; then
      echo "$filename 是 block device"
    elif [[ -c $filename ]]; then
      echo "$filename 是 character device"
    fi
    if [[ -L $filename ]]; then
      echo "$filename 是一个软链接"
    fi
    # 对于软链接,使用-L测试时,当链接指向的目标文件不存在时会返回false
    if [[ -L $filename || -e $filename ]]; then
      echo "$filename 存在 (可能是失效的链接)"
    fi
     
    if [[ -L $filename && ! -e $filename ]]; then
      echo "$filename 是失效的软链接"
    fi
    
  8. 内容既输出到控制台也输出到文件里

    
    echo 'ok'| tee -a bb.log
    
  9. 处理退出信号

    trap "rm -f ${lock_file}; echo 'exited ok.'" SIGINT SIGQUIT
    
    # SIGHUP:从终端终止或退出正在前台运行的进程
    # SIGINT:从键盘按下 Ctrl-C
    # SIGQUIT:从键盘按下 Ctrl-\
    # SIGTERM :软件终止信号
    
  10. 处理参数

    if [[ "$OSTYPE" == "darwin"* ]]; then
        # Mac OSX ( brew install gnu-getopt )
        getopt_cmd="$(brew --prefix gnu-getopt)/bin/getopt"
    else
        # linux-gnu
        getopt_cmd="getopt"
    fi
    long_opts="once,name:,note:"
    
    opts=$($getopt_cmd -n $0 -o - --long $long_opts -- "$@")
    
    eval set -- "$opts"
    
    while : 
    do
        case "$1" in
        --once)
            once="true" ; shift 1 ;;
        --name)
            name=$2  ; shift 2 ;;
            --note)
                note=$2  ; shift 2 ;;
        --)
            shift ; break ;;
        *)
        echo "参数错误" ; exit 1 ;;
    esac
    done
    echo "once: ${once:-no}, name: ${name}, note: ${note}"
    
  11. MySQL 查询

    std_log='/var/log/test.log'
    err_log='/var/log/test.err.log'
    
    user='root'
    pwd=''
    host='127.0.0.1'
    db='mysql'
    
    exec_sql() {
        echo "exec_sql: $1" | tee -a ${std_log}
        mysql -u${user} -p${pwd} -h${host} -D${db} -s -N -e "$1" | tee -a ${std_log}
    }
    exec_sql "show databases"
    
  12. 标准输入输出重定向

shell中,每个进程都和三个系统文
件相关联:标准输入stdin,标准输出stdout和标准错误stderr,三个系统文件的文件描述符分别为0, 1, 2
在使用 mysql 命令获取结果时会有一些警告信息
mysql: [Warning] Using a password on the command line interface can be insecure.
但是我要得到命令的结果不需要这些警告, 这个时候就需要重定向错误输出到其他地方
num=`mysql -u${user} -p${pwd} -h${host} -D${db} -s -N -e "${count_sql}" 2>${err_log}

注意

此为个人这一周以来的小总结,并非专业的 shell 教程,旨在能帮助懂编程的人不会 shell 的能快速上手,少走一些我趟过的坑,减少一些搜索。
有些原理我也不是太清楚,以后需要的时候才会去系统学习吧,现在这些已经能完成任务了。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容