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.

     

  • 相关阅读:
    51nod乘积之和
    Dell服务器安装OpenManage(OMSA)
    Nginx反向代理PHP
    搭建haproxy
    108. Convert Sorted Array to Binary Search Tree
    60. Permutation Sequence
    142. Linked List Cycle II
    129. Sum Root to Leaf Numbers
    118. Pascal's Triangle
    26. Remove Duplicates from Sorted Array
  • 原文地址:https://www.cnblogs.com/silence-hust/p/4534616.html
Copyright © 2011-2022 走看看