• 参数展开与特殊字符


    ${var:-word},var存在且非null,则返回其值,否则返回word。即变量未定义返回默认值。

    ${var:=word},var存在且非null,则返回其值,否则将var设置为word并返回word。即变量未定义测设为默认值。

    ${var:?errormsg},var存在且非null,则返回其值,否则显示var:errormsg错误信息,并退出当前命令或脚本。

    ${var:+word},var存在且非null,则返回word,否则返回null。

    每个运算符内的冒号:都是可选的,如果省略则每个定义中的"存在且非null"改为"存在".

    username2 = ${username2:-`whoami`}
    DEFAULT_FILENAME=generic.data
    filename=${1:-$DEFAULT_FILENAME}
    dummy_variable=${ZZXy23AB?"ZXy23AB has not been set."}
    a=${param4:+xyz}

    模式匹配:假设path=/home/tolstoy/mem/long.file.name

    ${var#pattern},如果模式匹配变量的开头处,则删除匹配的最短部分并返回剩下的部分。

    ${var##pattern},如果模式匹配变量的开头处,则删除匹配的最长部分并返回剩下的部分。

    ${var%pattern},如果模式匹配变量的结尾处,则删除匹配的最短部分并返回剩下的部分。

    ${var%%pattern},如果模式匹配变量的结尾处,则删除匹配的最长部分并返回剩下的部分。

    例:

    ${path#/*/}结果为toltoy/mem/long.file.name

    ${path##/*/}结果为long.file.name  一个"#"表示匹配最短, "##"表示匹配最长

    ${path%.*}结果为/home/toltoy/mem/long.file

    ${path%%.*}结果为/home/toltoy/mem/long  一个"%"表示匹配最短, "%%"表示匹配最长.

    return=${1#0} # "1"表示的是"$1" -- 传递进来的参数. "0"就是我们想从"$1"中删除的子串-- 去掉零.

     变量长度/子串删除

    ${#var}
    字符串长度(变量$var得字符个数). 对于array来说, ${#array}表示的是数组中第一个元素的长度.

    例外情况:

    ${#*}和${#@}表示位置参数的个数.
    对于数组来说, ${#array[*]}和${#array[@]}表示数组中元素的个数.

    变量扩展/子串替换
    ${var:pos}   变量var从位置pos开始扩展(也就是pos之前的字符都丢弃).
    ${var:pos:len} 变量var从位置pos开始, 并扩展len个字符.
    ${var/Pattern/Replacement} 使用Replacement来替换变量var中第一个匹配Pattern的字符串. 如果省略Replacement, 那么第一个匹配Pattern的字符串将被替换为空, 也就是被删除了.
    ${var//Pattern/Replacement} 全局替换. 所有在变量var匹配Pattern的字符串, 都会被替换为Replacement.和上边一样, 如果省略Replacement, 那么所有匹配Pattern的字符串, 都将被替换为空, 也就是被删除掉.

    ${var/#Pattern/Replacement} 如果变量var的前缀匹配Pattern, 那么就使用Replacement来替换匹配到Pattern的字符串.
    ${var/%Pattern/Replacement} 如果变量var的后缀匹配Pattern, 那么就使用Replacement来替换匹配到Pattern的字符串.

    ${!varprefix*}, ${!varprefix@} 匹配所有之前声明过的, 并且以varprefix开头的变量.

    xyz23=whatever     xyz24=

    a=${!xyz*} # 展开所有以"xyz"开头的, 并且之前声明过的变量名.         echo "a = $a" # a = xyz23 xyz24

    a=${!xyz@} # 同上.    echo "a = $a" # a = xyz23 xyz24

    shell变量$#,$@,$0,$1,$2的含义解释: 

    变量说明: 
    $$ Shell本身的PID(ProcessID) 
    $! :Shell最后运行的后台Process的PID 
    $? :最后运行的命令的结束代码(返回值) 
    $- :使用Set命令设定的Flag一览 
    $* :所有参数列表。如"$*"用「"」括起来的情况、以"$1 $2 … $n"的形式输出所有参数。 
    $@ :所有参数列表。如"$@"用「"」括起来的情况、以"$1" "$2" … "$n" 的形式输出所有参数。 
    $# :添加到Shell的参数个数 
    $0 :Shell本身的文件名 
    $1~$n :添加到Shell的各参数值。$1是第1参数、$2是第2参数…。 

    $@与$*中的参数只有在被双引号引用起来的时候才会不同.

    $? : 命令, 函数, 或者是脚本本身的(参见例子 23-7)退出状态码

    分号;可以在同一行写两个语句,"if"和"then"也需要分隔。

    终止case选项[双分号, 即;;].

    冒号的作用:

    1. 空命令,等价于“NOP”,也可被认为与shell的内建命令true的作用相同 ":"命令是一个bash的内建命令, 它的退出码(exit

    status)是"true"(0).

    2. 死循环:

    while :
    do
       operation-1
       operation-2
       ...
       operation-n
    done
    
    # Same as:
    #    while true
    #    do
    #      ...
    #    done

    3.在if/then中的占位符:

    if condition
    then :   # Do nothing and branch ahead
    else     # Or else ...
       take-some-action
    fi

    4.在一个二元命令中提供一个占位符

    : ${username=`whoami`}
    # ${username=`whoami`}   Gives an error without the leading :
    #                        unless "username" is a command or builtin...
    
    : ${1?"Usage: $0 ARGUMENT"}     # From "usage-message.sh example script.

    5.使用参数替换来评估字符串变量

    : ${HOSTNAME?} ${USER?} ${MAIL?}

    6.在与>重定向操作符结合使用时, 将会把一个文件清空, 但是并不会修改这个文件的权限. 如果之

    前这个文件并不存在, 那么就创建这个文件.

    : > data.xxx   # File "data.xxx" now empty.	      
    
    # Same effect as   cat /dev/null >data.xxx
    # However, this does not fork a new process, since ":" is a builtin.

     在与>>重定向操作符结合使用时, 将不会对预先存在的目标文件(: >> target_file)产生任何影

    响. 如果这个文件之前并不存在, 那么就创建它.

     7. ":"还用来在/etc/passwd和$PATH变量中做分隔符.

    bash$ echo $PATH
    /usr/local/bin:/bin:/usr/bin:/usr/X11R6/bin:/sbin:/usr/sbin:/usr/games

     *的作用:通配符[星号, 即*]. *可以用来做文件名匹配的"通配符".含义是, 可以用来匹配给定目录下的任何文件名.   *也可以用在正则表达式中, 用来匹配任意个数(包含0个)的字符.

    ?:通配符. ?在通配中, 用来做匹配单个字符的"通配符", 在正则表达式中, 也是用来表示一个字符.

    ():命令组,在括号中的命令列表, 将会作为一个子shell来运行.在括号中的变量,由于是在子shell中,所以对于脚本剩下的部分是不可用的.父进程, 也就是脚本本身, 将不能够读取在子进程中创建的变量, 也就是在子shell中创建的变量.

    初始化数组.  Array=(element1 element2 element3)

    {}

    大括号扩展.   cat {file1,file2,file3} > combined_file   # 把file1, file2, file3连接在一起, 并且重定向到combined_file中.
    cp file22.{txt,backup}  # 拷贝"file22.txt"到"file22.backup"中

    代码块[大括号, 即{}]. 又被称为内部组, 这个结构事实上创建了一个匿名函数(一个没有名字的函数). 然而, 与"标准"函数不同的是, 在其中声明的变量,对于脚本其他部分的代码来说还是可见的.

     例子 3-1. 代码块和I/O重定向

    #!/bin/bash
    # Reading lines in /etc/fstab.
    
    File=/etc/fstab
    
    {
    read line1
    read line2
    } < $File
    
    echo "First line in $File is:"
    echo "$line1"
    echo
    echo "Second line in $File is:"
    echo "$line2"
    
    exit 0
    例子 3-2. 将一个代码块的结果保存到文件
    #!/bin/bash
    # rpm-check.sh
    
    #  Queries an rpm file for description, listing,
    #+ and whether it can be installed.
    #  Saves output to a file.
    # 
    #  This script illustrates using a code block.
    
    SUCCESS=0
    E_NOARGS=65
    
    if [ -z "$1" ]
    then
      echo "Usage: `basename $0` rpm-file"
      exit $E_NOARGS
    fi  
    
    { # Begin code block.
      echo
      echo "Archive Description:"
      rpm -qpi $1       # Query description.
      echo
      echo "Archive Listing:"
      rpm -qpl $1       # Query listing.
      echo
      rpm -i --test $1  # Query whether rpm file can be installed.
      if [ "$?" -eq $SUCCESS ]
      then
        echo "$1 can be installed."
      else
        echo "$1 cannot be installed."
      fi  
      echo              # End code block.
    } > "$1.test"       # Redirects output of everything in block to file.
    
    echo "Results of rpm test in file $1.test"
    
    # See rpm man page for explanation of options.
    
    exit 0
     与上面所讲到的()中的命令组不同的是, {大括号}中的代码块将不会开启一

    个新的子shell.

     > &> >& >> < <> 重定向.

    scriptname >filename 重定向scriptname的输出到文件filename中. 如果filename存在的话, 那么将会被覆盖.
    command &>filename 重定向command的stdout和stderr到filename中.
    command >&2 重定向command的stdout到stderr中.
    scriptname >>filename 把scriptname的输出追加到文件filename中. 如果filename不存在的话,将会被创建.

    [[ ]]测试Test expression between [[ ]]. More flexible than the single-bracket [ ] test, this is a shell keyword.

    进程替换.(command)>   ,  <(command)

    <, >正则表达式中的单词边界 . bash$ grep '<the>' textfile

    |  管道. 分析前边命令的输出, 并将输出作为后边命令的输入. 这是一种产生命令链的好方法.cat $filename1 $filename2 | grep $search_word

    >|强制重定向(即使设置了noclobber选项 -- 就是-C选项). 这将强制的覆盖一个现存文件.

    || 或-逻辑操作. 在一个条件测试结构中, 如果条件测试结构两边中的任意一边结果为true的话,||操作就会返回0(代表执行成功).

    & 后台运行命令. 一个命令后边跟一个& 表示在后台运行.  在一个脚本中,命令和循环都可能运行在后台.

    &&  与-逻辑操作. 在一个条件测试结构中, 只有在条件测试结构的两边结果都为true的时候, &&操作才会返回0(代表sucess).

    - 用于重定向stdin或stdout[破折号, 即-].

    (cd /source/directory && tar cf - . ) | (cd /dest/directory && tar xpvf -)
    # Move entire file tree from one directory to another
    # [courtesy Alan Cox <a.cox@swansea.ac.uk>, with a minor change]
    
    # 1) cd /source/directory
    #    Source directory, where the files to be moved are.
    # 2) &&
    #   "And-list": if the 'cd' operation successful,
    #    then execute the next command.
    # 3) tar cf - .
    #    The 'c' option 'tar' archiving command creates a new archive,
    #    the 'f' (file) option, followed by '-' designates the target file
    #    as stdout, and do it in current directory tree ('.').
    # 4) |
    #    Piped to ...
    # 5) ( ... )
    #    a subshell
    # 6) cd /dest/directory
    #    Change to the destination directory.
    # 7) &&
    #   "And-list", as above
    # 8) tar xpvf -
    #    Unarchive ('x'), preserve ownership and file permissions ('p'),
    #    and send verbose messages to stdout ('v'),
    #    reading data from stdin ('f' followed by '-').
    #
    #    Note that 'x' is a command, and 'p', 'v', 'f' are options.
    #
    # Whew!
    
    
    
    # More elegant than, but equivalent to:
    #   cd source/directory
    #   tar cf - . | (cd ../dest/directory; tar xpvf -)
    #
    #     Also having same effect:
    # cp -a /source/directory/* /dest/directory
    #     Or:
    # cp -a /source/directory/* /source/directory/.[^.]* /dest/directory
    #     If there are hidden files in /source/directory.
    bunzip2 -c linux-2.6.16.tar.bz2 | tar xvf -
    #  --uncompress tar file--      | --then pass it to "tar"--
    #  If "tar" has not been patched to handle "bunzip2",
    #+ this needs to be done in two discrete steps, using a pipe.
    #  The purpose of the exercise is to unarchive "bzipped" kernel source.

    例子 3-4 备份最后一天所有修改的文件

    #!/bin/bash
    
    #  Backs up all files in current directory modified within last 24 hours
    #+ in a "tarball" (tarred and gzipped file).
    
    BACKUPFILE=backup-$(date +%m-%d-%Y)
    #                 Embeds date in backup filename.
    #                 Thanks, Joshua Tschida, for the idea.
    archive=${1:-$BACKUPFILE}
    #  If no backup-archive filename specified on command-line,
    #+ it will default to "backup-MM-DD-YYYY.tar.gz."
    
    tar cvf - `find . -mtime -1 -type f -print` > $archive.tar
    gzip $archive.tar
    echo "Directory $PWD backed up in archive file "$archive.tar.gz"."
    
    
    #  Stephane Chazelas points out that the above code will fail
    #+ if there are too many files found
    #+ or if any filenames contain blank characters.
    
    # He suggests the following alternatives:
    # -------------------------------------------------------------------
    #   find . -mtime -1 -type f -print0 | xargs -0 tar rvf "$archive.tar"
    #      using the GNU version of "find".
    
    
    #   find . -mtime -1 -type f -exec tar rvf "$archive.tar" '{}' ;
    #         portable to other UNIX flavors, but much slower.
    # -------------------------------------------------------------------
    
    
    exit 0
     -  先前的工作目录. cd -将会回到先前的工作目录.
    + 某些命令内建命令使用+来打开特定的选项, 用-来禁用这些特定的选项.

    ~+ 当前工作目录. 相当于$PWD内部变量.

    ~-先前的工作目录. 相当于$OLDPWD内部变量.

     

    使用双引号还能够阻止单词分割(word splitting). [3]如果一个参数被双引号扩起来的话, 那么这个参数将认为是一个单元, 即使这个参数包含有空白, 那里面的单词也不会被分隔开.
     variable1="a variable containing five words"
    COMMAND This is $variable1 # 用下面7个参数执行COMMAND命令:
     # "This" "is" "a" "variable" "containing" "five" "words"

    COMMAND "This is $variable1" # 用下面1个参数执行COMMAND命令:
    # "This is a variable containing five words"


    variable2="" # Empty.

    COMMAND $variable2 $variable2 $variable2 # COMMAND将不带参数执行.
    COMMAND "$variable2" "$variable2" "$variable2" # COMMAND将以3个空参数来执行.
    COMMAND "$variable2 $variable2 $variable2" # COMMAND将以1个参数来执行(2空格).

    在echo语句中, 只有在单词分割(word splitting)或者需要保留空白的时候, 才需要把参数用双引号括起来.

  • 相关阅读:
    JSON.parse()和JSON.stringify()
    对于火狐浏览器中title不能换行自动变成...怎么解决的?
    Python中文编码过程中遇到的一些问题
    【Java并发编程实战】—–“J.U.C”:ReentrantLock之二lock方法分析
    PHP CURL 中文说明
    Windows系统下正确安装MongoDB
    js笔试题
    记录真实想法,在路上不断前行——关于工作,学习,职场
    Ansible@一个高效的配置管理工具--Ansible configure management--翻译(十一)
    Java第四次作业
  • 原文地址:https://www.cnblogs.com/fly-xiang-zhao/p/3675575.html
Copyright © 2020-2023  润新知