美文网首页Shell
Shell Script要点review

Shell Script要点review

作者: KevinCool | 来源:发表于2016-04-05 23:20 被阅读125次

    1.shell既是一种命令语言,又是一种程序设计语言
    2.Batch批处理,写一个shell脚本,shell一次把这些命令执行完
    3.解释执行,不需要编译,shell程序从脚本中一行一行的读取并执行这些命令
    4.常见的shell脚本解释器有bash,sh,csh,ksh
    5.bash是liunx默认的shell,sh是Unix默认的shell,bash完全兼容sh,sh写的脚本可以直接在bash中执行
    6.编译型语言,C,C++,Java都是编译型语言,需要预先将写好的源代码转换成目标代码,称为编译,运行程序时候,直接读取目标代码,
    由于目标代码非常接近底层,因此效率很高。但是运作于底层,处理的是字节,整数,浮点数或者其他机器层级的对象,所以实现一个简单的功能需要大量代码
    7.解释型语言,脚本语言,解释器读取源代码并将其转换成目标代码,再由计算机运行,每次执行程序都多了编译过程,因此效率有所下降。awk,Python,Ruby,Shell
    8.一个例子

    #!/bin/bash
    echo "hello world"```
    其中#!表示这个脚本需要用什么解释器来执行,比如还有`#!/usr/bin/env python`
    使用vim退出保存的时候,`:wq filename.sh`
    
    ####9.运行shell脚本
    `chmod +x ./test.sh #使得脚本具有可执行权限`
    `./test.sh #执行脚本`
    或者直接运行解释器,参数是shell脚本的文件名,
    `/bin/sh test.sh`
    `bash test.sh`
    
    ####10.另外一个脚本,read的使用方法,read -p "comment"
    

    !/bin/bash

    Author: Kevin

    echo "what is your name?"
    read -p "please enter in your name: " PERSON
    echo "hello,$PERSON"```

    11.定义变量

    variableName="value"#中间没有空格

    12.使用变量

    your_name="mozhiyan"
    echo $your_name
    echo ${your_name}#加上花括号是为了确定变量的边界
    #比如这样
    for skill in Ada Coffe Action Java
    do
        echo "i am good at ${skill}script"
    done```
    只有使用变量的时候才加美元符号。定义的时候,重新定义的时候都不需要
    readonly将变量定义为只读变量
    readonly variablename
    
    使用unset删除变量
    unset variable_name
    
    三种变量类型
    局部变量,仅在shell实例中有效,
    环境变量,系统的环境变量
    shell变量,shell程序设置的特殊变量
    
    ####13.一些特殊变量
    $表示当前shell进程的ID,pid
    echo $$
    

    $0 表示当前脚本的文件名,也就是第0个参数
    $n 传递给脚本函数的第几个参数
    $# 表示传递给脚本函数的参数个数
    $* 表示传递给脚本或者函数的所有参数,不加引号,分开输出,"$"会将所有参数作为整体输出
    $@ 也是所有参数,分开输出,但是如果是这样 "$@" 会将参数分开输出
    $? 表示上个命令的退出状态,或者函数的返回值
    也就是说$@不论是什么情况,都会分开输出参数
    但是$
    在普通情况下会分开输出,但是"$*"会整体输出```

    14.shell替换

    在双引号中使用变量就是一种替换,转义字符也是一种替换,表达式中含有特殊字符,也会替换

    #!/bin/bash
    a=10
    echo -e "value of a is $a \n"```
    使用-e参数表示对转义字符进行替换,如果不使用将原样输出
    \\ \a 警报 \b退格 \f 换页 \n \r回车 \t 水平制表 \v 垂直制表
    
    ####15.命令替换
    使用\`command\`或者$(command)
    shell先执行命令,将输出结果暂时保存,在适当的地方输出
    

    !/bin/bash

    DATE=date
    echo "Date is $DATE"
    USERS=$(ls test.sh)#wc 显示文件的行数
    echo "Logged in users are $USERS"
    UP=date;uptime
    echo "Uptime is $UP"```

    16.变量替换

    ${var}变量本来的值
    ${var:-word}如果变量为空或被删除,返回word,不改变var的值,-后面的内容是作为字符串输出的,加上双引号会更好
    ${var:=word}如果变量为空或被删除,返回word,将var值设置为word
    ${var:+word}如果变量被定义,那么返回word,但是不改变var的值,没有定义,返回空值
    ${var:?message}如果变量为空或者被删除,那么将消息message送到标准错误输出,用来检测变量var是否可以被正常赋值,如果有值就输出这个值

    17.shell运算符

    原生bash不支持简单的数学运算,但是可以通过其他命令来实现,awk或者expr
    expr可以完成表达式求值操作

    #!/bin/bash
    val=`expr 2 + 2`
    echo "total value:$val"```
    2 + 2之间必须要有空格,即表达式和运算符之间要有空格,如果没有就变成字符串打印2+2了
    另外乘号*前面必须有反斜杠\才能实现乘法运算
    条件表达式要在方括号之内,并且要有空格,[ $a == $b ],$a,$b与方括号之间也要有空格
    ==用于比较两个数字相等
    
    关系运算符
    -eq相等返回True,-ne不相等,-gt大于,-lt小于,-ge大于等于,-le小于等于
    
    布尔运算符
    -a 与运算,-o 或运算 !非运算
    
    字符串运算符
    =两个字符串相等,!=不相等,-z字符串长度为0,-n字符串长度不为0,str,[ $a ]字符串不为空
    if [ -z $a ],if [ $a ]
    
    文件测试运算符
    用于检测文件的各种属性
    
    ####18.注释
    使用#,而且没有多行注释,只能每一行加一个#号
    如果需要将大段的代码注释起来,过一会取消注释,可以用花括号把这段代码括起来,定义成一个函数,然后没有地方调用这个函数,就起到注释的效果
    
    ####19.字符串
    使用单引号
    单引号里面所有特殊字符都无效,原样输出所有字符,并且也不出现转义字符,不能输出变量
    str='this is a string'
    
    使用双引号
    双引号里面可以有变量,可以出现转义字符
    

    拼接字符串

    your_name="qinjx"
    greeting="hello,"$your_name"!"

    双引号将使用变量的表达式括起来只是起到不混淆的作用,也可以不用双引号

    greeting_1="hello,${your_name}!"
    echo $greeting$greeting_1```

    获取字符串长度
    echo ${#string}

    提取子字符串,从0开始
    echo ${string:1:4}

    查找子字符串,is是要查的字符串,如果没有返回0,如果有,返回从1开始的index
    echo \expr index "$string" is` `

    20.数组

    bash支持一维数组,不支持多维数组,从0开始
    定义数组
    array_name=(value0 value1 value2)#使用空格将数组元素分割开
    单独定义数组各个分量

    array_name[0]=value0
    array_name[1]=value1
    array_name[2]=value2
    #下标的范围没有限制,没有定义的元素的值就是空```
    
    读取数组
    

    ${array_name[0]}

    使用@或者*可以读取数组所有元素

    ${array_name[*]}
    ${array_name[#]}```

    获取数组长度

    #取得数组元素个数
    length=${#array_name[@]}
    length=${#array_name[*]}
    #取得数组单个元素的长度
    lengthe=${#array_name[n]}```
    
    ####21.echo命令
    echo用于在屏幕上打印出指定的字符串
    echo arg 或者 echo "arg" 默认都会作为字符串
    
    显示转义字符
    `echo "\"It is a test \""`
    
    显示变量
    

    name="OK"
    echo "$name It is a test"```
    如果变量与其他字符相连的话,使用大括号
    mouth=9
    echo ""$month"-1-2009"
    echo "${month}-1-2009"

    显示换行
    echo "OK\n"
    转义转义字符
    echo -e "OK\n"

    显示结果重定向至文件
    echo "it is a test">myfile

    原样输出字符串,使用单引号
    echo '$name\"'

    显示命令执行结果
    echo \date` `

    22.printf命令

    printf命令用于格式化输出,echo命令的增强,移植性比echo好
    printf "Hello,shell\n"
    echo会自动换行,printf必须显式添加换行符
    printf format-string [arguments...]

    以下例子
    printf "%d %s\n" 1 "abc"
    如果参数多于格式控制符的话,format-string可以重用,将所有参数都转换
    printf %s abc def输出abcdef
    如果没有arguments,%s用NULL代替,%d用0代替,arguments使用空格分隔,不用逗号。
    printf "%f" 1.233

    例子脚本

    #!/bin/bash
    #Author: Kevin
    #Description: It's a script about the printf command practice
    printf "%d %s\n" 1 "abc"
    printf '%d %s\n' 1 "abc"
    #舗o "" can be output too
    printf %s avcdef
    printf "%s\n" abc def
    printf %s abc def
    printf "%s %s %s\n" a b c d e f g h i j```
    
    ####23.if else语句
    if ... fi
    if .. else .. fi
    if .. elif .. else .. fi
    
    例子
    

    if [ $a == $b ]
    then
    echo "a is equal to b"
    fi```

    $[2*3]这种方式可以直接计算出里面表达式的值
    if test $[2*3] -eq $[1+5];then echo 'the two numbers are equal';fi;

    同时if else语句也经常与test命令结合使用
    test命令用于检查某个条件是否成立,与[]的作用是一样的
    比如[ $a == $b ] 和 test $a == $b

    #!/bin/bash
    #Author: Kevin
    #Description: It is a script about the ifelse expression
    a=10
    b=20
    if [ $a == $b ]
    then
            echo "a is equal to b"
    elif [ $a -gt $b ]
    then
            echo "a is greater than b"
    elif [ $a -lt $b ]
    then
            echo "a is less than b"
    else
            echo "none if the condition met"
    fi
    
    if test $[2*3] -eq $[1+5];then echo "the two numbers are equal";fi;
    
    num1=$[2*3]
    num2=$[1+5]
    if test $[num1] -eq $[num2]
    then
            echo "the two numbers are equal"
    else
            echo "the two numbers are not equal"
    fi```
    
    
    ####24.case...esac语句
    多分枝选择结构
    case语句匹配一个值或者一个模式,匹配成功,执行相匹配的命令
    

    case 值 in
    模式1) command
    ;;
    模式2) command
    ;;
    *) command
    ;;
    esac```

    每一模式必须以右括号结束,取值可以是变量或者常数,所有命令开始执行至;;
    如果无一匹配则使用星号捕获该值,再执行后面的命令

    #!/bin/bash
    #Author: Kevin
    #Description: It is a script about the case ... esac statement
    echo "Input a number between 1 to 4"
    echo -e "your number is : \c"
    read aNum
    case $aNum in
            1) echo "you select 1"
            ;;
            2) echo "you select 2"
            ;;
            3) echo "you select 3"
            ;;
            4) echo "you select 4"
            ;;
            *) echo "you do not select a number between 1 to 4"
            ;;
    esac```
    
    另一个例子
    

    !/bin/bash

    Author: Kevin

    Description: It is a script about the case ... esac

    options="${1}"
    case $options in
    -f) FILE="${2}"
    echo "FILE name is $FILE"
    ;;
    -d) DIR="${2}"
    echo "Dir name is $DIR"
    ;;
    *)
    echo "basename ${0}:usage:[-f file]|[-d directory]"
    exit 1 #command to come out of the program with status 1
    ;;
    esac```
    basename输出最后一个文件名
    使用"${1}"来将输入分隔开作为一个整体

    25.for循环

    for 变量 in 列表
    do
        command
    done```
    列表是一组值,数字,字符串,每个值通过空格分隔,每循环一次,就把列表中下一个值赋给变量
    for loop in 1 2 3 4 5; do    echo "the value is $loop"; done
    
    `for str in "this is a string";do echo $str;done`
    只有一个值,是this is a string
    
    for file in ./*.sh;do echo $file;done
    显示以sh结尾的所有文件
    
    ####26.while循环
    

    while command
    do
    statements
    done```
    测试条件为真的时候执行

    counter=0
    while [ $counter -lt 5 ]
    do
        counter=`expr $counter + 1`
        #counter=$[$counter+1]
        #counter=$(expr $counter + 1)
        echo $counter
    done```
    
    一个例子
    

    !/bin/bash

    Author: Kevin

    Description: It is a script about while statement

    counter=0
    while [ $counter -lt 5 ]
    do
    counter=expr $counter + 1
    echo $counter
    done
    echo "it's done"
    counter=0
    while [ $counter -le 10 ]
    do
    counter=$(expr $counter + 1)
    echo $counter
    done
    echo "it's done"
    while [ $counter -lt 20 ]
    do
    #这个[]表达式就是求值的,但是里面的元素$counter取变量值还是一样的
    counter=$[$counter+1]
    echo $counter
    done```

    另外一个while例子

    #!/bin/bash
    #Author: Kevin
    #Description: a while statements expression
    echo "type <ctrl+D> to terminate"
    echo -n "enter your most liked film: "
    while read Film
    do
        echo "yeah,great film the $Film"
    done```
    
    ####27.until循环
    until循环执行一系列命令直到条件为True时候停止
    

    until command
    do
    statement
    done```
    command为条件表达式,返回值为false,继续执行循环体语句,否则跳出循环

    一个例子

    #!/bin/bash
    #Author: Kevin
    a=0
    until [ ! $a -lt 10 ]
    do
        printf "%d\n" $a
        a=$(expr $a + 1)
    done```
    
    ####28.break
    echo -n不换行输出
    

    !/bin/bash

    Author: Kevin

    while :
    do
    echo -n "Input a number between 1 to 5:"
    read aNum
    case $aNum in
    1|2|3|4|5) echo "your number is $aNum!"
    ;;
    *) echo "you do not select a number between 1 to 5, game is over!"
    break
    ;;
    esac
    done```
    关注while:用法
    break n表示跳出第n层循环
    一个嵌套循环的例子

    #!/bin/bash
    #Author: Kevin
    for var1 in 1 2 3
    do
        for var2 in 0 5
        do
            if [ $var1 -eq 2 -a $var2 == 0 ]
            then
                break 2
            else
                echo "$var1 $var2"
            fi
        done
    done```
    
    continue跳出当前循环
    

    !/bin/bash

    Author: Kevin

    while :
    do
    echo -n "Input a number between 1 to 5:"
    read aNum
    case $aNum in
    1|2|3|4|5) echo "your number is $aNum!"
    ;;
    *) echo "you do not select a number between 1 to 5, game is over!"
    continue
    echo "game is over"
    ;;
    esac
    done```
    按道理game is over不会出现,但是实际运行会运行到
    continue后面跟一个数字,表示跳出第几层循环

    29.函数

    function_name(){
        list of commands
        [return value]
    }```
    如果不加return,最后一条命令运行结果作为返回值
    shell 函数返回值只能是整数,表示函数执行成功与否,0表示成功
    如果要让函数返回字符串,定义一个变量,用来接收函数的计算结果,然后脚本访问这个变量来获得函数返回值
    
    调用函数只需要函数名,不需要加括号
    函数返回值在调用该函数后通过$?来获得
    
    一个例子
    

    !/bin/bash

    hello(){
    echo "it's you"
    }

    hello```

    另外一个例子

    #!/bin/bash
    funWithReturn(){
            echo "the function is to get the sum of two numbers..."
            echo -n "Input first number: "
            read aNum
            echo -n "Input another number: "
            read anotherNum
            echo "the two numbers are $aNum and $anotherNum !"
            return $(($aNum+$anotherNum))
        #return $[$aNum+$anotherNum]
    }
    
    funWithReturn
    
    ret=$?
    echo "the sum of two numbers is $ret !"```
    
    另一个例子
    函数嵌套
    

    !/bin/bash

    number_one(){
    echo "i love you!"
    number_two
    }
    number_two(){
    echo "me too"
    }
    number_one```

    删除函数
    unset .f function_name
    如果需要从终端调用函数,可以将函数定义在主目录下的.profile文件,这样每次登陆之后,在命令提示符后面输入函数名字就可以立即调用

    30.函数参数

    使用$n来获取参数的值,但是n>=10的时候就要使用${n}来获取参数了
    $#参数个数,$*所有参数,$@所有参数,$?函数返回值

    #!/bin/bash
    funWithParam(){
            echo "fisrt parameter is $1"
            echo "third parameter is $3"
            echo "tenth parameter is ${10}"
            echo "eleventh parameter is ${11}"
            echo "the amout of the parameter is $#"
            echo "the string of the parameter is $*"
            echo "another version of the all parameter is $@"
            echo "all parameter \$* is "$*""
            echo "all parameter \$@ is "$@""
    }
    
    funWithParam 1 2 3 4 5 6 7 8 9 10 11 12 14```
    
    ####31.输入输出重定向
    命令输出可以是显示器,也可以是文件
    command > file
    并且输出重定向会覆盖文件内容
    如果要追加,那么使用>>追加到文件末尾
    echo line 2 >> users
    
    ll > list
    ls >> list
    
    输入重定向
    command < file
    从文件中获取输入,本从键盘获取的输入命令会转移到文件读取内容
    wc命令 -l 表示显示一个文件的行数,wc -c filename显示一个文件的字节数
    wc -m filename显示一个文件的字符数 wc -w filename显示一个文件的字数
    wc -l < list
    
    每个linux命令运行时都会打开3个文件
    标准输入文件stdin,文件描述符为0
    标准输出文件stdout,文件描述符为1
    标准错误文件stderr,文件描述符为2
    
    command > file 将stdout重定向到file,command < file 将stdin 重定向为file
    
    将stderr重定向到file,command 2 > file
    追加到文件末尾,command 2 >> file
    
    将stdout 和 stderr 合并后重定向到file
    command > file 2>&1
    或者
    command >> file 2>&1
    对stdin和stdout都重定向
    command < file > file2
    
    n>&m将输出文件m和n合并
    n<&m将输入文件m和n合并
    
    Here Document
    嵌入文档,shell中特殊的重定向方式
    

    command << delimiter
    document
    delimiter```
    将两个delimiter之间的内容作为输入传递给command

    wc -l << EOF
        This is a simple lookup program
        for good and bad restaurants
        in cape town.
    EOF```
    
    /dev/null文件
    如果希望执行某个命令,但是想丢弃输出结果,将输出重定向之/dev/null
    command > /dev/null
    如果要屏蔽stdout和stderr
    command > /dev/null 2>&1
    将stdout 和 stderr 合并后重定向到/dev/null
    
    ####32.文件包含
    包含外部脚本,将外部脚本内容合并到当前脚本
    . filename # .命令
    source filename
    
    被包含脚本不需要有执行权限
    1.subscript.sh
    

    url="www.baidu.com"```

    2.main.sh

    #!/bin/bash
    . ./subscript.sh
    echo $url```

    相关文章

      网友评论

        本文标题:Shell Script要点review

        本文链接:https://www.haomeiwen.com/subject/funplttx.html