zoukankan      html  css  js  c++  java
  • Shell脚本学习笔记-语法

    Solaris下Shell脚本学习笔记。

    Shell语法
    Shell中变量都是全局的,如果需要在函数中使用局部变量,在变量前加上local
    'expression'单引号括起的表达式中不允许变量扩展;
    "expression"双引号中则允许,可以用来连接变量, fullname="$firstname $lastname"
    (expression1;expression2;...)括号中的指令形成指令群,也成为subshell,
        其中定义的变量作用范围限定于指令群本身,也不会对主脚本的状态产生影响.
        例如tar cf - * | ( cd /tmp/; tar -xf -) 执行完毕后当前目录不会改变
    ((expression)) 和let命令类似用于算术运算
         ((b=10**2)); echo $b; 等同于let b=10**2; **表示乘方
    {} 大括号可用来表示逗号隔开的字符串的组合,
        ls ab{c,d}.txt  相当于 ls abc.txt abd.txt;
        mkdir {ab,cd}ef{12,34} 相当于mkdir abef12 abef34 cdef12 cdef34

    $? 上次执行的shell返回结果
    $$ 代表进程ID;
    $!最后一个后台命令的进程ID(可供稍后调用wait使用);
    $PPID 父进程ID;

    $PS1命令提示符,默认为$;
    $PS2 行继续提示符,默认为>;
    $PS4 用set -x打开跟踪,执行跟踪的提示符,默认为+

    $1, $2...${10}... 读取脚本中的参数, 超过9加大括号; $0为指令本身; $#为变量的总数.
    $@("$@"="$1" "$2" "$3" ...)或者$*("$*"= "$1 $2 $3 ...")列出所有的参数,
        在不加双引号的情况下,两者相同

    ${VAR-DEFAULT} 或者 ${VAR=DEFAULT} 使用一个默认值来代替那些不存在的变量;
        如果变量不存在后者同时会导致VAR被设置为DEFAULT.
    ${VAR:-DEFAULT} 或者 ${VAR:=DEFAULT} 使用一个默认值来代替那些不存在或者值为空的变量;
        如果变量不存在或者为空后者同时会导致VAR被设置为DEFAULT.
    ${VAR?MSG} 如果变量不存在显示出错误MSG并中止脚本的执行同时返回退出码1,否则返回VAR;
    ${VAR:?MSG} 如果变量不存在或者为空显示错误MSG并中止脚本的执行同时返回退出码1,否则返回VAR;

    ${VAR+MSG} 如果变量不存在就会返回null,否则返回MSG;
    ${VAR:+MSG} 如果变量不存在或者值为空就返回null,否则返回MSG
    ${#VAR} 变量的长度
    ${VAR%word} 如果word匹配变量结尾部分,删除匹配的最短部分,然后返回剩余部分
    ${VAR%%word} 如果word匹配变量结尾部分,删除匹配的最长部分,然后返回剩余部分
    ${VAR#word} 如果word匹配变量开始部分,删除匹配的最短部分,然后返回剩余部分
    ${VAR##word} 如果word匹配变量开始部分,删除匹配的最长部分,然后返回剩余部分

    $(command) 或者 `command` 返回当前执行命令的结果
    $((...)) 对括号内的表达式求值, 例如 x=2; x=$(($x**3)); echo $x

    : 不做任何事情,只作参数展开,但是返回值为0. :>file 等同于 cat /dev/null > file;
    . 读取文件并执行文件中的内容,注意是在当前shell进程中执行,变量赋值,函数定义,改变目录等影响都是全局的

    使用read读取输入时默认行为是把输入行尾的反斜杠看作续行符, -r选项可以不把看作续行符.
    使用read读取输入时使用$IFS进行字段切分.例如
        while IFS=: read user password uid gid fullname homedir shell
        do
              echo $user $password $uid $gid $fullname $homedir $shell
        done < /etc/passwd
    *在执行某个命令时临时修改某个变量: PATH=.:/usr/bin test.sh
    *输入重定向置于循环体结尾,也可以使用管道 cat /etc/passwd | while ...
    *读取密码stty -echo;read pass < /dev/tty;stty echo;

    eval命令读取它的参数然后把结果作为command给shell执行,
    在变量替换或命令输出作为命令执行的情况下,比较有用.
    例如, x="ls | more", 分别执行$x 和eval $x, 前者不能得到正确结果。

    xargs utility [arguments]命令在标准输入上取得参数列表,
    再将它们以适当大小(ARG_MAX)组装起来加在utility [arguments]后面.
    这在命令行长度超过限制(ARG_MAX)的情况下非常有用.例如,
    find /usr/include -type f | xargs grep POSIX_OPEN_MAX /dev/null
    *ARG_MAX可以用getconf ARG_MAX来查看。

    command在查找待执行的命令时,避开shell函数; -p 查找命令时,使用$PATH的默认值

    shell查找命令的顺序:特殊内建命令->shell函数->一般内建命令->$PATH目录下的外部命令
    特殊内建命令有: . break continue eval exec exit export readonly return set shift times trap unset
    一般内建命令有: alias bg cd command false fc fg getopts jobs kill newgrp pwd read true umask unalias wait
    所以可以用shell函数来覆盖一般内建命令,例如
    cd () {
    command cd "$@"
    x=`pwd`
    PS1="${x##*/}$ "
    }

    cd - 变更工作目录到上一次工作目录
    cd ~或者cd 变更工作目录到当前用户目录
    cd ~user变更工作目录到user用户目录

    test命令
    -e file 是否存在; -d file 是否目录; -f file 是否一般文件; -h file | -L file 是否符号链接;
    -s file 是否文件为空
    -r file; -w file; -x file 是否可读;是否可写;是否可执行文件或者可被查找的目录
    -n string 是否string不为null; -z string 是否string为null;
    s1 = s2 字符串相同(注意=符号前后的空格); s1 != s2 字符串不相同
    n1 -eq n2; n1 -ne n2; n1 -lt n2; n1 -gt n2; n1 -le n2; n1 -ge n2 整数比较
    *前置!表示否定结果; -a 逻辑与; -o 逻辑或
    *所有的变量展开都加上"",防止变量本身为空引起的问题,例如 test -f "$FILE"
    *[] 中括号用于条件判断符号,可理解为指向test命令的一个软链接,用法可完全参照test.
        注意紧挨着括号要有空格,例如 if [ ! -f file ]

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

    case $1 in
    valueA)
    ...
    ;;
    valueB | valueC)
    ...
    ;;
    *)
    ...
    ;;
    esac

    for i [in list]
    do
    ...
    done
    *in list可选,如果省略等同in "$@", 循环整个参数列表.
    *list的写法例: for i in 3 4 5; for i in *.txt; for i in {1..10}; for ((i=1;i<=10;++i))

    { while | until } condition
    do
    ...
    done

    利用getopts命令处理输入参数.
    file= verbose= quiet= long=

    while getopts :vqf:l opt
    do
      case $opt in
      v) verbose=true
         quiet=
         ;;
      q) quiet=true
         verbose=
         ;;
      f) file=$OPTARG
         ;;
      l) long=true
         ;;
      ?) echo "$0: invalid option -$OPTARG" >&2
         echo "Usage: $0 [-f file] [-vql] [files...]" >&2
         exit 1
         ;;
      esac
    done
    shift $((OPTIND - 1))
    *选项后面的:表示该选项必须提供一个参数.getopts会把参数值放到变量OPTARG中.
    *OPTIND被设置为下一个待处理参数的索引值.
    *:作为选项字符串的第一个字符,会导致针对非法选项
        1)不输出错误信息;
        2)将变量$opt设置为?并且把非法选项放到变量OPTARG中.
    *最后的shift $((OPTIND - 1))删除所有选项.留下参数,可以利用$1,$2...获得.
    *注意OPTIND是全局的,如果某个函数也需要调用getopts来解析自己的参数,需要重设OPTIND为1.

    <<可以在脚本中提供嵌入输入并可以在嵌入文件中使用变量替换,
    cat << EOF
    ...
    $HOME
    ...
    EOF
    *如果要避免发生变量替换,可以把定界符用引号括起来,例如 cat << 'EOF'
    *使用<<-形式则删除嵌入文本中每一行开始的tab(空格不会删除),这样可以提高shell脚本的可读性

    exec命令可以用来进行IO重定向,改变文件描述符,例如
    exec 3<file
    read arg1 arg2 < &3
    再例如,
    exec 99>&2     文件描述符99指向标准错误输出
    exec 2>/tmp/$0.log  文件描述符2指向文件
    ...
    exec 2>&99    恢复文件描述符2为标准错误输出
    exec 99>&-    关闭文件描述符99

    set命令
    1)不带参数的set打印所有的shell变量
    2)+-分别表示关闭/打开特定的shell选项。($- 表示当前已经打开的shell选项)
    -a allexport,export所有后续定义的变量
    -b notify,立即显示作业完成的信息,而不是等待下一个提示符。
    -C noclobber,打开防止覆盖,>重定向遇到目标文件存在就会失败,这种情况下可以使用>|来做重定向。
    -e errexit,命令退出值非零则退出shell。
    -f noglob,停用通配符展开
    -m monitor,打开作业控制(默认是打开的)
    -n noexec,读取命令并且检查语法错误但是不执行。在交互式shell下忽略此选项。
    -u nounset,视未定义的变量为错误而不是作为null。
    -v verbose,在执行命令前打印命令行,不做变量替换。
    -x xtrace,在执行命令前打印命令行,做变量替换。另一种方式 bash -x scriptfile。
    - 关闭-v -x选项。 

    trap命令用来捕获信号 trap 'command' signal lis
    信号可以用数字也可以用名字,可以使用man signal.h查看对应关系.
    除了标准信号trap还提供一个特殊信号EXIT或者0,表示脚本正常终止。

  • 相关阅读:
    IBM WebSphere MQ 7.5基本用法
    IBM WebSphere MQ介绍安装以及配置服务详解
    Windows平台上使用Github搭建Git服务器的图文教程
    Git安装和TortoiseGit详细使用教程【基础篇】
    DOS命令之at命令详解
    单元测试数据库 -- 使用事物回滚测试
    VS中实时获取SVN的版本号并写入到AssemblyInfo.cs中
    SQL2008中Merge的用法
    VS版本号定义、规则和相关的Visual Studio插件
    JSON字符串互相转换的三种方式和性能比较
  • 原文地址:https://www.cnblogs.com/weixun/p/3262029.html
Copyright © 2011-2022 走看看