• linux基础3


    shell脚本

    变量

    定义

    命名规范:

    • 命名只能使用英文字母,数字和下划线,首个字符不能以数字开头。
    • 中间不能有空格,可以使用下划线(_)。
    • 不能使用标点符号。
    • 不能使用bash里的关键字(可用help命令查看保留关键字)。

    示例

    1
    2
    varname="value" #不能空格
    name="Lebron James" 变量值中有空格要用双引号

    有效的

    1
    2
    3
    LD_LIBRARY_PATH
    _var
    var2

    无效的

    1
    2
    ?var=123
    user*name=runoob

    语句赋值

    1
    2
    3
    for file in `ls /etc`

    for file in $(ls /etc)

    使用变量

    引用:

    • $yourval
    • ${yourval}

    注意:

    • ${val}用来标识变量边界
    • “$val”可防止变量为空引发的异常

    只读变量

    使用 readonly 命令可以将变量定义为只读变量,只读变量的值不能被改变。

    下面的例子尝试更改只读变量,结果报错:

    1
    2
    3
    4
    !/bin/bash
    myUrl="http://www.google.com"
    readonly myUrl
    myUrl="http://www.runoob.com"

    删除变量

    使用 unset 命令可以删除变量。语法:

    1
    unset variable_name

    变量被删除后不能再次使用。unset 命令不能删除只读变量。

    变量类型

    运行shell时,会同时存在三种变量:

    1) 局部变量 局部变量在脚本或命令中定义,仅在当前shell实例中有效,其他shell启动的程序不能访问局部变量。

    若不声明local,则函数中的变量也为全局变量。
    若声明为local(local var=200),则变量的作用域只在函数内。
    

    2) 环境变量 所有的程序,包括shell启动的程序,都能访问环境变量,有些程序需要环境变量来保证其正常运行。必要的时候shell脚本也可以定义环境变量。
    3) shell变量 shell变量是由shell程序设置的特殊变量。shell变量中有一部分是环境变量,有一部分是局部变量,这些变量保证了shell的正常运行

    位置参数

    ${n}:输入的第n个参数($0表示脚本名字)$1,$2...
    $#:输入参数的数量
    $@:输入的所有参数
    $!:输入的最后一个参数
    $?:上一个命令的返回值(用于在脚本中判断之前命令的执行状态,任何非0的返回都表示非正常执行)
    

    字符串

    单引号(强引用)

    1
    str='this is a string'

    单引号字符串的限制:

    • 单引号里的任何字符都会原样输出,单引号字符串中的变量是无效的;
    • 单引号字串中不能出现单独一个的单引号(对单引号使用转义符后也不行),但可成对出现,作为字符串拼接使用。

    双引号(弱引用)

    1
    str="Hello, I know you are "$your_name"! n"

    双引号的优点:

    • 双引号里可以有变量
    • 双引号里可以出现转义字符

    拼接字符串

    1
    2
    3
    4
    5
    6
    7
    8
    9
    your_name="runoob"
    使用双引号拼接
    greeting="hello, "$your_name" !"
    greeting_1="hello, ${your_name} !"
    echo $greeting $greeting_1
    使用单引号拼接
    greeting_2='hello, '$your_name' !'
    greeting_3='hello, ${your_name} !'
    echo $greeting_2 $greeting_3

    输出结果为:

    1
    2
    hello, runoob ! hello, runoob !
    hello, runoob ! hello, ${your_name} !

    长度

    1
    2
    3
    4
    5
    6
    string="abcd"
    echo ${#string} #输出 4
    string="hello,everyone my name is xiaoming"
    expr length "$string"
    输出:34
    注意:string字符串里边有空格,所以需要添加双引号

    截取

    假设有变量 var=http://www.aaa.com/123.htm

    • # 号截取,删除左边字符,保留右边字符。
    1
    echo ${var#*//}

    其中 var 是变量名,# 号是运算符,*// 表示从左边开始删除第一个 // 号及左边的所有字符

    即删除 http://

    结果是 :www.aaa.com/123.htm

    • ## 号截取,删除左边字符,保留右边字符。
    1
    echo ${var##*/}

    ##*/ 表示从左边开始删除最后(最右边)一个 / 号及左边的所有字符

    即删除 http://www.aaa.com/

    结果是 123.htm

    • %号截取,删除右边字符,保留左边字符
    1
    echo ${var%/*}

    %/* 表示从右边开始,删除第一个 / 号及右边的字符

    结果是:http://www.aaa.com

    • %% 号截取,删除右边字符,保留左边字符
    1
    echo ${var%%/*}

    %%/* 表示从右边开始,删除最后(最左边)一个 / 号及右边的字符

    结果是:http:

    • 从左边第几个字符开始,及字符的个数
    1
    echo ${var:0:5}

    其中的 0 表示左边第一个字符开始,5 表示字符的总个数。

    结果是:http:

    • 从左边第几个字符开始,一直到结束。
    1
    echo ${var:7}

    其中的 7 表示左边第8个字符开始,一直到结束。

    结果是 :www.aaa.com/123.htm

    • 从右边第几个字符开始,及字符的个数
    1
    echo ${var:0-7:3}

    其中的 0-7 表示右边算起第七个字符开始,3 表示字符的个数。

    结果是:123

    • 从右边第几个字符开始,一直到结束。
    1
    echo ${var:0-7}

    表示从右边第七个字符开始,一直到结束。

    结果是:123.htm

    注:(左边的第一个字符是用 0 表示,右边的第一个字符用 0-1 表示)

    替换

    1. ${var/pattern/pattern}表示将var字符串的第一个匹配的pattern替换为另一个pattern。
    2. ${var//pattern/pattern}表示将var字符串中的所有能匹配的pattern替换为另一个pattern。

    查找

    查找字符 i 或 o 的位置(哪个字母先出现就计算哪个):

    1
    2
    string="runoob is a great site"
    echo `expr index "$string" io` # 输出 4

    注意: 以上脚本中 ` 是反引号,而不是单引号 ‘,不要看错了哦。

    默认值

    1. ${var:-string}和${var:=string}:若变量var为空,则用在命令行中用string来替换${var:-string},否则变量var不为空时,则用变量var的值来替换${var:-string};对于${var:=string}的替换规则和${var:-string}是一样的,所不同之处是${var:=string}若var为空时,用string替换${var:=string}的同时,把string赋给变量var: ${var:=string}很常用的一种用法是,判断某个变量是否赋值,没有的话则给它赋上一个默认值。
    2. ${var:+string}的替换规则和上面的相反,即只有当var不是空的时候才替换成string,若var为空时则不替换或者说是替换成变量 var的值,即空值。(因为变量var此时为空,所以这两种说法是等价的)
    3. ${var:?string}替换规则为:若变量var不为空,则用变量var的值来替换${var:?string};若变量var为空,则把string输出到标准错误中,并从脚本中退出。我们可利用此特性来检查是否设置了变量的值。

    读取字符

    read [-options] [variable..]

    以下实例读取键盘输入的内容并将其赋值给shell变量,为:-p 参数由于设置提示信息:

    1
    2
    3
    4
    read -p "input a val:" a    #获取键盘输入的 a 变量数字
    read -p "input b val:" b #获取键盘输入的 b 变量数字
    r=$[a+b] #计算a+b的结果 赋值给r 不能有空格
    echo "result = ${r}" #输出显示结果 r

    测试结果:

    1
    2
    3
    input a val:1
    input b val:2
    result = 3

    数组

    定义数组

    数值类型的数组:一对括号表示数组,数组中元素之间使用“空格”来隔开。
    举个列子:
    arr_number=(1 2 3 4 5);
    字符串类型数组:同样,使用一对括号表示数组,其中数组中的元素使用双引号或者单引号包含,同样使用“空格”来隔开。
    arr_string=(“abc” “edf” “sss”); 或者 arr_string=(‘abc’ ‘edf’ ‘sss’);

    操作

    获取长度
    1
    arr_length=${#arr_number[*]}或${#arr_number[@]}均可,即形式:${#数组名[@/*]} 可得到数组的长度。
    下标赋值

    这里需要提出两个问题:
    第一个问题是如果该下标元素已经存在,会怎么样?
    答:会修改该下标的值为新的指定值。
    例如:arr_number[2]=100,数组被修改为(1 2 100 4 5)
    第二个问题是如果指定的下标已经超过当前数组的大小,如上述的arr_number的大小为5,指定下标为10或者11或者大于5的任意值会如何?
    答:新赋的值被追加到数组的尾部。
    例如:arr_number[13]=13,数组被修改为(1 2 100 4 5 13)

    删除操作

    清除某个元素:unset arr_number[1],这里清除下标为1的数组;
    清空整个数组:unset arr_number;

    分片访问

    分片访问形式为:${数组名[@或*]:开始下标:结束下标},注意,不包括结束下标元素的值。
    例如:${arr_number[@]:1:4},这里分片访问从下标为1开始,元素个数为4。

    模式替换

    形式为:${数组名[@或*]/模式/新值}
    例如:${arr_number[@]/2/98}

    数组的遍历

    数组遍历我们使用for语句来演示:

    1
    2
    3
    for v in ${arr_number[@]}; do
    echo $v;
    done
    大专栏  linux基础3gure>

    流程控制

    if

    test 或 [ ]

    整数判断 字符串判断 逻辑判断 文件判断
    -eq 等于 -z 为空 -a 并(&&) -r file 可读
    -lt 小于 -n 不为空 -o 或( ) -w file 可写
    -gt 大于 = 等于 -x file 可执行
    -le 小于等于 != 不等于 -f file 是否为文件
    -ge 大于等于 > 大于 -d dir 是否为目录
    -ne 不等于 < 小于 -s 非空

    例子

    1
    2
    3
    4
    5
    6
    7
    if [ "$grade" -gt 90 ];then 
    echo ">90"
    elif [ "grade" -gt 80 ];then
    echo ">80"
    else
    echo "other"
    fi

    case

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    case $1 in
    start|s)
    echo service is running
    ;;
    stop)
    echo service is stoped
    ;;
    reload)
    echo service is reload
    ;;
    *)
    echo xxxxx
    ;;
    esac

    for

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    #写法1
    for var in 1 2 3 4 5 #(ps:或者for var in $(seq 1 5)或者for var in {1..5})
    do
    echo -n "$val "
    done
    #写法2
    for((i=0;i<10;i++)) #( ps:必须是for(( )) )
    {
    let "val=i%2"
    if [ $val -ne 0 ]; then
    echo "${i} is a odd number"
    fi
    }

    while

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    #写法 1
    while read line # ( ps:while读取是按行读,常用于文本按行读取 )
    do
    if [ "$line" -eq 5 ]; then
    echo "5"
    break
    fi
    done # ( ps:写成 done < data.txt 则重定向从data.txt中按行读取数据)
    #写法 2
    res=10
    while [ $res -gt 0 ]
    do
    echo -n "$res "
    let "res-=1"
    done
    echo "done"

    数值计算

    expr

    加减乘除

    1
    2
    $a=$(expr 1 + 3)#注意空格
    $b=$(expr 1 * 3)#注意转义

    AWK

    加减乘除乘方可小数可对小数判断大小

    1
    2
    $a=$(echo""|awk "{print 2^4}")
    echo "" | awk '{if(.5<1){print "ok"}}'

    bc

    1
    2
    $a=$(echo "scale=2;ibase=2;obase=10;111+111" | bc)
    $b=`echo "1+3" | bc`

    let

    1
    2
    let "sum+=1"
    let "j=sum%2"

    $(())

    1
    $a=$((1+1))

    特殊

    括号

    ()
    1. 命令组。括号中的命令将会新开一个子shell顺序执行,所以括号中的变量不能够被脚本余下的部分使用。括号中多个命令之间用分号隔开,最后一个命令可以没有分号,各命令和括号之间不必有空格。
    2. 命令替换。等同于`cmd`,shell扫描一遍命令行,发现了$(cmd)结构,便将$(cmd)中的cmd执行一次,得到其标准输出,再将此输出放到原来命令。有些shell不支持,如tcsh。
    3. 用于初始化数组。如:array=(a b c d)
    (())
    1. 整数扩展。这种扩展计算是整数型的计算,不支持浮点型。((exp))结构扩展并计算一个算术表达式的值,如果表达式的结果为0,那么返回的退出状态码为1,或者 是”假”,而一个非零值的表达式所返回的退出状态码将为0,或者是”true”。若是逻辑判断,表达式exp为真则为1,假则为0。
    2. 只要括号中的运算符、表达式符合C语言运算规则,都可用在$((exp))中,甚至是三目运算符。作不同进位(如二进制、八进制、十六进制)运算时,输出结果全都自动转化成了十进制。如:echo $((16#5f)) 结果为95 (16进位转十进制)
    3. 单纯用 (( )) 也可重定义变量值,比如 a=5; ((a++)) 可将 $a 重定义为6
    4. 常用于算术运算比较,双括号中的变量可以不使用$符号前缀。括号内支持多个表达式用逗号分开。 只要括号中的表达式符合C语言运算规则,比如可以直接使用for((i=0;i<5;i++)), 如果不使用双括号, 则为for i in `seq 0 4`或者for i in {0..4}。再如可以直接使用if (($i<5)), 如果不使用双括号, 则为if [ $i -lt 5 ]。
    []
    1. bash 的内部命令,[和test是等同的。如果我们不用绝对路径指明,通常我们用的都是bash自带的命令。if/test结构中的左中括号是调用test的命令标识,右中括号是关闭条件判断的。这个命令把它的参数作为比较表达式或者作为文件测试,并且根据比较的结果来返回一个退出状态码。if/test结构中并不是必须右中括号,但是新版的Bash中要求必须这样。
    2. Test和[]中可用的比较运算符只有==和!=,两者都是用于字符串比较的,不可用于整数比较,整数比较只能使用-eq,-gt这种形式。无论是字符串比较还是整数比较都不支持大于号小于号。如果实在想用,对于字符串比较可以使用转义形式,如果比较”ab”和”bc”:[ ab < bc ],结果为真,也就是返回状态为0。[ ]中的逻辑与和逻辑或使用-a 和-o 表示。
    3. 字符范围。用作正则表达式的一部分,描述一个匹配的字符范围。作为test用途的中括号内不能使用正则。
    4. 在一个array 结构的上下文中,中括号用来引用数组中每个元素的编号。
    [[]]
    1. [[是 bash 程序语言的关键字。并不是一个命令,[[ ]] 结构比[ ]结构更加通用。在[[和]]之间所有的字符都不会发生文件名扩展或者单词分割,但是会发生参数扩展和命令替换。
    2. 支持字符串的模式匹配,使用=~操作符时甚至支持shell的正则表达式。字符串比较时可以把右边的作为一个模式,而不仅仅是一个字符串,比如[[ hello == hell? ]],结果为真。[[ ]] 中匹配字符串或通配符,不需要引号。
    3. 使用[[ … ]]条件判断结构,而不是[ … ],能够防止脚本中的许多逻辑错误。比如,&&、||、<和> 操作符能够正常存在于[[ ]]条件判断结构中,但是如果出现在[ ]结构中的话,会报错。比如可以直接使用if [[ $a != 1 && $a != 2 ]], 如果不适用双括号, 则为if [ $a -ne 1] && [ $a != 2 ]或者if [ $a -ne 1 -a $a != 2 ]。

      ④bash把双中括号中的表达式看作一个单独的元素,并返回一个退出状态码。

    例子

    1
    2
    3
    4
    5
    6
    7
    8
    9
    if ($i<5)
    if [ $i -lt 5 ]
    if [ $a -ne 1 -a $a != 2 ] #-a不能用&&替代
    if [ $a -ne 1] && [ $a != 2
    if [[ $a != 1 && $a != 2 ]]
    for i in $(seq 0 4);do echo $i;done
    for i in `seq 0 4`;do echo $i;done
    for ((i=0;i<5;i++));do echo $i;done
    for i in {0..4};do echo $i;done
    {}
    1. 常规用法

      1. 大括号拓展。(通配(globbing))将对大括号中的文件名做扩展。在大括号中,不允许有空白,除非这个空白被引用或转义。第一种:对大括号中的以逗号分割的文件列表进行拓展。如 touch {a,b}.txt 结果为a.txt b.txt。第二种:对大括号中以点点(..)分割的顺序文件列表起拓展作用,如:touch {a..d}.txt 结果为a.txt b.txt c.txt d.txt

        1
        2
        3
        4
        5
        6
        # ls {ex1,ex2}.sh 
        ex1.sh ex2.sh
        # ls {ex{1..3},ex4}.sh
        ex1.sh ex2.sh ex3.sh ex4.sh
        # ls {ex[1-3],ex4}.sh
        ex1.sh ex2.sh ex3.sh ex4.sh
      2. 代码块,又被称为内部组,这个结构事实上创建了一个匿名函数 。与小括号中的命令不同,大括号内的命令不会新开一个子shell运行,即脚本余下部分仍可使用括号内变量。括号内的命令间用分号隔开,最后一个也必须有分号。{}的第一个命令和左括号之间必须要有一个空格。

    2. 几种特殊的替换结构
      见上

  • 相关阅读:
    December 23rd 2016 Week 52nd Friday
    December 22nd 2016 Week 52nd Thursday
    December 21st 2016 Week 52nd Wednesday
    December 20th 2016 Week 52nd Tuesday
    December 19th 2016 Week 52nd Sunday
    December 18th 2016 Week 52nd Sunday
    uva294(唯一分解定理)
    uva11624Fire!(bfs)
    fzu2150Fire Game(双起点bfs)
    poj3276Face The Right Way
  • 原文地址:https://www.cnblogs.com/lijianming180/p/12409582.html
Copyright © 2020-2023  润新知