zoukankan      html  css  js  c++  java
  • shell脚本学习笔记

    1、判断符号:中括号[ ]

    [ ]进行数据的判断,例如我想知道HOME这个变量是否为空,[ -z "$HOME" ],或者两个字符串是否相等,[ "$HOME"  ==  "$MALI" ]。由于中括号使用的地方有很多,所以在bash中作为判断式时,中括号的两端需要有空格来分隔。在使用中需要注意:

    • 在中括号内的每个组件都需要有空格键来分隔

    • 在中括号内的变量,最好以双引号括号起来,例如"$HOME"

    • 在中括号内的常量,最好以单或者双引号括起来,

    read -p "please input (Y/N)" yn

    [ "$yn" == "Y" -o  "$yn" == "y" ] && echo "OK continue" && exit 0

    [ "$yn" == "N" -o  "$yn" == "n" ] && echo "Oh, interrupt" && exit 0

     

    2、shell的默认变量

    $0  :执行脚本的完整文件名    $1:第一个参数    $2:第二个参数 …………

    $#:代表后接的参数“个数”

    $@:参数内容,代表“$1”“$2”“$3”,每个变量是独立的

    $*:代表“$1c$2c$3c$4”c为分隔符,一般为空格,

    $$:脚本本身的进程PID

    shift变量:shift n 会移动变量,去除第n个变量,变量集体左移以为,第一位消失。

     测试脚本:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    #!/bin/bash
    echo "the script name is:   ==> $0"
    echo "total parameter number is :   ==> $#"
    echo "your whole parameter is:   ==> $@"
    echo "your whole parameter222 is:   ==> $@"
    echo "the 1st parameter is:   ==> $1"
    echo "the 2st parameter is:   ==> $2"
    shift 2
    echo "After shift total parameter number is :   ==> $#"
    echo "After shift the 1st parameter is:   ==> $1"

    结果:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    ./sh07.sh I Love You
    the script name is:   ==> ./sh07.sh
    total parameter number is :   ==> 3
    your whole parameter is:   ==> I Love You
    your whole parameter222 is:   ==> I Love You
    the 1st parameter is:   ==> I
    the 2st parameter is:   ==> Love
    After shift total parameter number is :   ==> 1
    After shift the 1st parameter is:   ==> You

     

    3、条件判断式

    if [  条件判读式一  ];then

        条件一成立

    elif [  条件判读式二  ];then

        条件二成立 

    else

        条件不成立

    fi

    if 命令不仅能测试由方括号括起来的条件,也能测试任何命令。if echo "$word" | grep -q "$letter_sequence";then

    当if和then在同一行的时候,一个分号(;)必须用在if语句的结尾。if和then都是关键字。关键字(或命令)开始一个语句,如果在同一行开始另一个新语句时,前面一个语句必须用分号(;)结束。

     

    用[[ ... ]]测试结构比用[ ... ]更能防止脚本里的许多逻辑错误。比如说,&&,||,<和>操作符能在一个[[]]测试里通过,但在[]结构会发生错误。在一个if的后面,不必一定是test命令或是test结构([]或是[[...]])

    break命令可以带一个参数.一个不带参数的break循环只能退出最内层的循环,而break N可以退出N层循环.

    continue命令也可以像break带一个参数.一个不带参数的continue命令只去掉本次循环的剩余代码.而continue N将会把N层循环剩余的代码都去掉,但是循环的次数不变。尽量避免.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    for outer in I II III IV V
    do           # 外部循环do
    echo; echo -n "Group $outer: "
         for inner in 1 2 3 4 5 6 7 8 9 10  # 内部循环
         do
            if "$inner" -eq 7 ]
            then
                continue 2  # continue 2层, 也就是到outer循环上.
                 # 将"continue 2"替换为一个单独的"continue"
                 # 来看一下一个正常循环的行为.
            fi 
     
             echo -n "$inner "  # 7 8 9 10 将不会被echo
        done 
    done

    case $变量名 in

        "第一个变量的内容")

            程序

            ;;

        

        "第一个变量的内容")

            程序

            ;;

        *)

            不包含第一个变量内容和第二个

            exit 1

            ;;

    esac

    不定循环

    while [ condition ]  #条件成立就循环

    do

        程序段

    done 

    或者 

    until [  condition  ]  #条件成立终止循环

    do

        程序段

    done

    固定循环

    for var in con1,con2,con3 …

    do

        程序段

    done

    适合数值处理for循环

    for ((初始值;限制值;步长))

    do

        程序段

    done

     

    4、函数function

    function fname(){

        函数内容

    }

    shell script的执行方式是从上到下的,所以一些函数需要在使用之前就给出。函数内有有内置变量的,调用的时候 fname one two,那么函数内的$1为one $2为two

    而script的内置变量$1,还是.sh后跟着的变量。

     

    5、shell的追踪和调试

    sh -n xx.sh:不要执行,仅查询语法错误

    sh -v xx.sh:在执行script之前先将内容输出到屏幕

    sh -x xx.sh:将使用到的script内容显示到屏幕上

     

    6、重定向

    > ;  &> ;  >&  ; >>

    scriptname >filename 重定向scriptname的输出到文件filename中去.,如果文件filename存在则将会被覆盖。

    command &> filename 会重定向命令command标准输出(stdout)和标准错误(stderr)到文件filename中。

    command >& 2  把命令command的标准输出(stdout)重定向到标准错误(stderr)。

    scriptname >>filename  把脚本scriptname的输出追加到文件filename.如果filename不存在,则它会被创建.

     

    7、变量

    variable是变量名,$variable就是引用这个变量的值,也是${variable}的一种简写形式。变量赋值的时候,=号两边都不能有空格。如果有一个空白符会怎么样?  如果用 "VARIABLE =value", 脚本会以为"VARIABLE"是一个命令并且此命令带了一个参数"=value"。 如果用 "VARIABLE= value", 脚本会以为"value"是一个命令,  并且把环境变量"VARIABLE"赋为空值:""。一个未初始化的变量有一个”null”值―表示从没有被赋值过(注意null值不等于零)。在一个变量从未赋值之前就使用它通常会引起问题。unset variable 销毁变量。

    变量赋值,可以使用= 、也可以使用单引号variable=`ls -l`,这个是将ls的结果赋给变量。也可以使用$(……),也是将括号内的结果赋给变量,variable=$(ls -l)。

    b=${a/23/BB}:将a中的"23"替换为"BB"并赋给变量b 反斜杠表示替换。

    在Bash中的变量是无类型的,允许变量有整数计算和比较。其中的决定因素是变量的值是不是只含有数字。

    环境变量,使用export导出,只能导出到子进程中,到由此脚本生成的命令或进程中。

    ${parameter-default}, ${parameter:-default}:如果变量没有被设置,使用默认值。

    ${parameter+alt_value}, ${parameter:+alt_value}:如果变量parameter设置,使用alt_value作为新值,否则使用空字符串。

    ${parameter?err_msg}, ${parameter:?err_msg}:如果变量parameter已经设置,则使用该值,否则打印err_msg错误信息。

     

    8、退出

    exit命令一般用于结束一个脚本,就像C语言的exit一样。它也能返回一个值给父进程。一个命令执行成功返回0,一个执行不成功的命令则返回一个非零值,此值通常可以被解释成一个对应的错误值。

    如果一个脚本以不带参数的exit命令结束,脚本的退出状态码将会是执行exit命令前的最后一个命令的退出码。脚本结束没有exit,不带参数的exit和exit $?三者是等价的,都是以最后命令的退出码退出脚本。

    $?变量保存了最后一个命令执行后的退出状态。当一个函数返回时,$?保存了函数里最后一个命令的退出状态码。这就是Bash里函数返回值的处理办法。当一个脚本运行结束,$? 变量保存脚本的退出状态,而脚本的退出状态则是脚本中最后一个已执行命令的退出状态。并且依照惯例,0表示执行成功,1-255的整数范围表示错误。$? 变量用于测试脚本中的命令执行结果非常的有用。

     

    逻辑非操作符!:反转一个命令或一个测试的结果,它也能反转退出状态。!后面需要跟一个空格,! true ==false,如果没有跟空格,则表示重复执行上次的命令。

    9、使用(( ... ))进行算术 

    (( ))结构扩展并计算一个算术表达式的值。如果表达式值为0,会返回1或假作为退出状态码。一个非零值的表达式返回一个0或真作为退出状态码。它和先前test命令及[]结构的讨论刚好相反。

    ((0))   $?值为1;((1))   $?值为0   ((表达式)):表达式的值为0,$?值为1,表达式的值为1,$?值为0。

    (( 5>9 ))   $?值为1;(( 5<9 ))   $?值为0   (( 表达式 )):表达式的值为false,$?值为1,表达式的值为true,$?值为0。

    shell程序中的操作默认都是字符串操作。

    let :可以使用let来指示下面是算术表达式,let表达式内变量不用加$,必须还完整的算术表达式,即有等号两边。这个可以等同于(( ))结构。let var=var+1  等同于 let "var = var + 1" 、let “var += 1”

    expr:通用求值表达式,通过给定的操作(参数必须以空格分开)连接参数,并对参数求值.可以使算术操作, 比较操作, 字符串操作或者是逻辑操作。expr 5 - 3、expr 5 * 3、y=`expr $y + 1` <==> let y=y+1 

    expr也可以用于字符串的操作:z=`expr substr $string $position $length`在位置$position上提取$length长度的子串。 

    b=`expr length $a`:长度: 字符串长度

    b=`expr substr $a 2 6`   # substr: 从指定位置提取指定长度的字串.

    b=`expr match "$a" '[0-9]*'`:从字符串的开始进行搜索,并匹配第一个匹配的字符串,使用正则表达式。  : 操作可以替换match. 比如, b=`expr $a : [0-9]*`与上边所使用的 b=`expr match $a [0-9]*` 完全等价.

     

     

    10、test 命令

    -e:文件是否存在

    -f:文件是一个普通文件(不是一个目录或是一个设备文件)

    -s:文件大小不为零

    -d:文件是一个目录

    -b:文件是一个块设备(软盘, 光驱, 等等.)

    -h:文件是一个符号链接

    -p:文件是一个管道

    -L:文件是一个符号链接

    -z:字符串为"null",即是指字符串长度为零。

    -n:字符串不为"null",即长度不为零.

    -r:文件是否可读 (指运行这个测试命令的用户的读权限)

    -w:文件是否可写 (指运行这个测试命令的用户的读权限)

    -x:文件是否可执行 (指运行这个测试命令的用户的读权限)

    f1 -nt f2:文件f1比f2新

    f1 -ot f2:文件f1比f2旧

    f1 -ef f2:文件f1和f2 是相同文件的硬链接

    !:"非" -- 反转上面所有测试的结果(如果没有给出条件则返回真).

    -eq:等于 if [ "$a" -eq "$b" ]

    -ne:不等于 if [ "$a" -ne "$b" ]

    -gt:大于 if [ "$a" -gt "$b" ]

    -ge:大于等于 if [ "$a" -ge "$b" ]

    -lt:小于 if [ "$a" -lt "$b" ]

    -le:小于等于 if [ "$a" -le "$b" ]

    <:小于(在双括号里使用)(("$a" < "$b"))  。if [[ "$a" < "$b" ]]  if [ "$a" < "$b" ] 注意"<"字符在[ ] 结构里需要转义

    <=:小于等于 (在双括号里使用)(("$a" <= "$b"))

    >:大于 (在双括号里使用)(("$a" > "$b"))

    >=:大于等于(在双括号里使用)(("$a" >= "$b"))

     

     

    11、字符串比较

     

    =:等于 if [ "$a" = "$b" ]         ==:等于 if [ "$a" == "$b" ]   它和=是同义词。==比较操作符在一个双方括号测试和一个单方括号号里意思不同。[[ $a == z* ]]    # 如果变量$a以字符"z"开始(模式匹配)则为真。[[ $a == "z*" ]]  # 如果变量$a与z*(字面上的匹配)相等则为真。

    字符串长度:${#string}、expr length $string、expr "$string" : '.*'

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

     

    索引:expr index $string $substring  ##在字符串$string中$substring第一次出现的数字位置

    子串提取:${string:position}  #把$string中从第$postion个字符开始字符串提取出来,如果$string是"*"或"@",则表示从位置参数中提取第$postion后面的字符串。

    ${string:position:length}  #把$string中$postion个字符后面的长度为$length的字符串提取出来。

    子串替换:${string/substring/replacement}    用$replacement替换由$substring匹配的第一个字符串。

    ${string//substring/replacement}     用$replacement替换所有匹配$substring的字符串。

    ${string/#substring/replacement}    如果$string字符串的最前端匹配$substring字符串,用$replacement替换$substring.

    ${string/%substring/replacement}    如果$string字符串的最后端匹配$substring字符串,用$replacement替换$substring.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    str=abcABC123ABCabc
    echo ${str/abc/xyz}
    echo ${str//abc/xyz}
    echo ${str/#abc/xyz}
    echo ${str/%abc/xyz}
    输出:
    xyzABC123ABCabc
    xyzABC123ABCxyz
    xyzABC123ABCabc
    abcABC123ABCxyz

    ${var#Pattern}, ${var##Pattern}:删除从$var前端开始的最短或最长匹配$Pattern的字符串。

    ${var%Pattern}, ${var%%Pattern}:删除从$var后端开始的最短或最长匹配$Pattern的字符串。

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

    1
    2
    3
    4
    5
    6
    7
    xyz23=whatever
    xyz24=
     
    a=${!xyz*}      # 展开为声明过的并以"xyz".
    echo "a = $a"   # a = xyz23 xyz24
    a=${!xyz@}      # Same as above.
    echo "a = $a"   # a = xyz23 xyz24

     

    12、declare

    declare或typeset内建命令(它们是完全相同的)可以用来限定变量的属性。这是在某些编程语言中使用的定义类型不严格的方式。

    declare -i var :将var限定成正数。eclare命令允许在声明变量类型的时候同时给变量赋值,declare -i var=88 

    -r :只读

    -i: 整数

    -a: 数组

    -f :函数  在脚本中没有带任何参数的declare -f 会列出所有在此脚本前面已定义的函数出来。

     

    13、shell命令和内部命令结合

    cat :把文件的内容输出到stdout. 当与重定向操作符 (> 或 >>)结合使用时, 一般都是用来将多个文件连接起来。cat file1,file2, file3 > file。-s选项可以把多个空行压缩成一个空行;-n 选项是为了在目标文件中的所有行前边插入行号;-b 选项 与 -n 选项一样, 区别是不对空行进行编号。

    rev:把每一行中的内容反转, 并且输出到 stdout上。 

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    bash$ cat file1.txt
    This is line 1.
    This is line 2.
     
    bash$ tac file1.txt
    This is line 2.
    This is line 1.
     
    bash$ rev file1.txt
    .1 enil si sihT
    .2 enil si sihT


    cp:cp file1 file2 把 file1 拷贝到 file2, 如果存在 file2 的话,那 file2 将被覆盖。 -a 归档 选项 (为了copy一个完整的目录树), -u 是更新选项, 和 -r 与 -R 递归选项.

    rm:删除(清除)一个或多个文件. -f 选项将强制删除文件,即使这个文件是只读的.并且可以用来避免用户输入(在非交互脚本中使用)。当使用递归参数 -r时, rm 命令将会删除整个目录树. 如果不慎使用 rm -rf *那整个目录树就真的完了。

    1
    2
    3
    4
    5
    cat list-1 list-2 list-3 | sort | uniq > final.list
    # 将3个文件连接起来,
    # 将它们排序,
    # 删除其中重复的行,
    # 最后将结果重定向到一个文件中.

    sort INPUTFILE | uniq -c | sort -nr 命令 先对 INPUTFILE 排序, 然后统计 每行出现的次数, 最后的(-nr 选项将会产生一个数字的反转排序). 这种命令模版一般都用来分析 log 文件或者用来分析字典列表, 或者用在那些需要检查文本词汇结构的地方。

     

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    $ cat testfile
     This line occurs only once.
     This line occurs twice.
     This line occurs twice.
     This line occurs three times.
     This line occurs three times.
     This line occurs three times
    $ uniq -c testfile
      1 This line occurs only once.
      2 This line occurs twice.
      3 This line occurs three times.
     
     
    $ sort testfile | uniq -c | sort -nr
      3 This line occurs three times.
      2 This line occurs twice.
      1 This line occurs only once.

     

  • 相关阅读:
    [转]SVN 乱码问题
    [转]自己做 Visual Studio 2013 代码折叠插件
    [Java]一步一步学 Web
    [转]SQL Server 结构读取
    [转][c#]注册表经验集
    [转]加密经验集 => C#
    [转]Oracle 连接dll
    《高效能程序员的修炼》读书笔记
    Blend for Visual Studio 2013
    ASP.NET中服务器控件的生命周期
  • 原文地址:https://www.cnblogs.com/silence-hust/p/4534616.html
Copyright © 2011-2022 走看看