zoukankan      html  css  js  c++  java
  • shell 脚本

    一 第一个shell

        #!/bin/bash
        echo "Hello World !"
    “#!” 是一个约定的标记,它告诉系统这个脚本需要什么解释器来执行,即使用哪一种Shell。echo命令用于向窗口输出文本。
     
    将上面的代码保存为test.sh,并 cd 到相应目录
    chmod +x ./test.sh  #使脚本具有执行权限
    ./test.sh  #执行脚本

    注意,一定要写成./test.sh,而不是test.sh。运行其它二进制的程序也一样,直接写test.sh,mac/linux系统会去PATH里寻找有没有叫test.sh的。一般来说只有/bin, /sbin, /usr/bin, /usr/sbin等在PATH里,你的当前目录通常不在PATH里,所以写成test.sh是会找不到命令的,要用. /test.sh告诉系统说,就在当前目录找

     
     
     

    二 变量

    (1)定义变量

    定义变量时,变量不加美元符号$,如
    var1="shell"
    var2=python

    注意,变量名和等号之间不能有空格,这可能和你熟悉的所有编程语言都不一样。同时,变量名的命名须遵循如下规则:

    • 首个字符必须为字母(a-z,A-Z)。
    • 中间不能有空格,可以使用下划线(_)。
    • 不能使用标点符号。
    • 不能使用bash里的关键字。

    (2)使用变量

    使用一个定义过的变量,只需要在变量名之前加美元符号$即可,如

    echo $var
    echo ${var}

    变量名外面的花括号是可选的,加不加都行,加花括号是为了帮助解释器识别变量的边界,比如下面这种情况:

        for skill in Ada Coffe Action Java 
        do
            echo "I am good at ${skill}Script"
        done

    如果不给skill变量加花括号,写成echo "I am good at $skillScript",解释器就会把$skillScript当成一个变量(其值为空),代码执行结果就不是我们期望的样子了。推荐给所有变量加上花括号,这是个好的编程习惯

      

    (3)只读变量

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

    var="java"
    readonly var
    var="php"

    运行脚本会报错提示是只读变量

    (4)删除变量

    使用 unset 命令可以删除变量.变量被删除后不能再次使用;unset 命令不能删除只读变量

    var="java"
    unset var
    echo $var

    上面的脚本没有任何输出

     

    (5)特殊变量

    特殊变量列表
    变量含义
    $0 当前脚本的文件名
    $n 传递给脚本或函数的参数。n 是一个数字,表示第几个参数。例如,第一个参数是$1,第二个参数是$2。
    $# 传递给脚本或函数的参数个数。
    $* 传递给脚本或函数的所有参数。
    $@ 传递给脚本或函数的所有参数。被双引号(" ")包含时,与 $* 稍有不同,下面将会讲到。
    $? 上个命令的退出状态,或函数的返回值。
    $$ 当前Shell进程ID。对于 Shell 脚本,就是这些脚本所在的进程ID。
     
     
     

    四 shell替换

    (1)转义字符替换

        #!/bin/bash
        a=10
        echo -e "Value of a is $a 
    "

    运行结果:

    Value of a is 10

    这里 -e 表示对转义字符进行替换。如果不使用 -e 选项,将会原样输出:

    Value of a is 10
    

    下面的转义字符都可以用在 echo 中:

    转义字符含义
    \ 反斜杠
    a 警报,响铃
     退格(删除键)
    f 换页(FF),将当前位置移到下页开头
    换行
    回车
    水平制表符(tab键) 
    v 垂直制表符
     
    可以使用 echo 命令的 -E 选项禁止转义,默认也是不转义的;使用 -n 选项可以禁止插入换行符。
     

    (2)命令替换

    命令替换是指Shell可以先执行命令,将输出结果暂时保存,在适当的地方输出。
    命令替换的语法:
    `command`

    注意是反引号,不是单引号,这个键位于 Esc 键下方。

    例如,
    #!/bin/bash
    DATE=`date`
    echo "Date is $DATE"

    运行结果:Date is 2015年 08月 26日 星期三 17:00:18 CST

     

    (3)变量替换

    变量替换可以根据变量的状态(是否为空、是否定义等)来改变它的值

    可以使用的变量替换形式:
    形式说明
    ${var} 变量本来的值
    ${var:-word} 如果变量 var 为空或已被删除(unset),那么返回 word,但不改变 var 的值。
    ${var:=word} 如果变量 var 为空或已被删除(unset),那么返回 word,并将 var 的值设置为 word。
    ${var:?message} 如果变量 var 为空或已被删除(unset),那么将消息 message 送到标准错误输出,可以用来检测变量 var 是否可以被正常赋值。
    若此替换出现在Shell脚本中,那么脚本将停止运行。
    ${var:+word} 如果变量 var 被定义,那么返回 word,但不改变 var 的值。
    例子如下:
    #!/bin/bash
    
    echo ${var:-"Variable is not set"}
    echo "1 - Value of var is ${var}"
    
    echo ${var:="Variable is not set"}
    echo "2 - Value of var is ${var}"
    
    unset var
    echo ${var:+"This is default value"}
    echo "3 - Value of var is $var"
    
    var="Prefix"
    echo ${var:+"This is default value"}
    echo "4 - Value of var is $var"
    
    echo ${var:?"Print this message"}
    echo "5 - Value of var is ${var}"

    运行结果:

     Variable is not set
    1 - Value of var is
    Variable is not set
    2 - Value of var is Variable is not set
    
    3 - Value of var is
    This is default value
    4 - Value of var is Prefix
    Prefix
    5 - Value of var is Prefix

    五 运算符

    bash支持很多运算符,包括算数运算符、关系运算符、布尔运算符、字符串运算符和文件测试运算符。原生bash不支持简单的数学运算,但是可以通过其他命令来实现,例如 awk 和 expr.

    expr 最常用, expr 是一款表达式计算工具,使用它能完成表达式的求值操作。

    例如两个数相加:

        #!/bin/bash
        val=`expr 2 + 2`
        echo "Total value : $val"

    运行脚本输出:

    Total value : 4

    两点注意:

    • 表达式和运算符之间要有空格,例如 2+2 是不对的,必须写成 2 + 2,这与我们熟悉的大多数编程语言不一样。
    • 完整的表达式要被 ` ` 包含,注意这个字符不是常用的单引号,在 Esc 键下边。

    算术运算符: 加法(+)  减法(-)  乘法(*)  除法(/)  取余(%)  赋值(=)    相等(==)   不相等(!=)

    注意:条件表达式要放在方括号之间,并且要有空格,例如 [$a==$b] 是错误的,必须写成 [ $a == $b ]。

    关系运算符:  -eq(相等返回 true)  -ne(不相等返回true)   -gt(左大于右返回true)  -lt(右大于左返回true)   -ge(左大于等于右返回true)   -le(右大于等于左返回true)

    布尔运算符:  !(非运算,表达式为true则返回false)  -o(或运算) -a(与运算)

    字符串运算符:  =(相等返回true)  !=(不相等返回true)  -z(字符串长度为0返回true)   -n(字符串长度不为0返回true)   [ $str ](字符串不为空返回true)

     例子: http://www.runoob.com/linux/linux-shell-basic-operators.html

     
     
     
     

    六 字符串

    字符串是shell编程中最常用最有用的数据类型(除了数字和字符串,也没啥其它类型好用了),字符串可以用单引号,也可以用双引号,也可以不用引号

    (1)单引号

        str='this is a string'
    单引号字符串的限制:
    • 单引号里的任何字符都会原样输出,单引号字符串中的变量是无效的;
    • 单引号字串中不能出现单引号(对单引号使用转义符后也不行)。

    (2)双引号

        your_name='qinjx'
        str="Hello, I know your are "$your_name"! 
    "

    双引号的优点:

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

    (3)拼接字符串

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

    (4)获取字符串长度

        string="abcd"
        echo ${#string} #输出 4

    (5)提取子字符串

        string="alibaba is a great company"
        echo ${string:1:4} #输出liba
     
     
     

    七 数组

    bash支持一维数组(不支持多维数组),并且没有限定数组的大小。类似与C语言,数组元素的下标由0开始编号。获取数组中的元素要利用下标,下标可以是整数或算术表达式,其值应大于或等于0

    (1)定义数组

    在Shell中,用括号来表示数组,数组元素用“空格”符号分割开。定义数组的一般形式为:  array_name=(value1 ... valuen)
        array_name=(value0 value1 value2 value3)

    还可以单独定义数组的各个分量:

        array_name[0]=value0
        array_name[1]=value1
        array_name[2]=value2

    可以不使用连续的下标,而且下标的范围没有限制。


    (2)读取数组

    读取数组元素值的一般格式是: ${array_name[index]},例如

        valuen=${array_name[2]}

    使用@ 或 * 可以获取数组中的所有元素,例如

        ${array_name[*]}
        ${array_name[@]}

    (3)获取数组的长度

    获取数组长度的方法与获取字符串长度的方法相同,例如:

        # 取得数组元素的个数
        length=${#array_name[@]}
        # 或者
        length=${#array_name[*]}
        # 取得数组单个元素的长度
        lengthn=${#array_name[n]}

    八 文件操作

    -f file    检测文件是否是普通文件(既不是目录,也不是设备文件),如果是,则返回 true。
    -d file    检测文件是否是目录,如果是,则返回 true。
    -r file     检测文件是否可读,如果是,则返回 true。
    -w file    检测文件是否可写,如果是,则返回 true。
    -x file     检测文件是否可执行,如果是,则返回 true。
     
    basename解析带路径的文件名称 
    var1=/usr/lib/abcdefg.so.bak  
    var2=/usr/sbin/ifconfiggg  
    all_name=`basename $var1`  
    sub_name1=`basename $var1 .bak`  
    sub_name2=`basename $var2 gg`  
          
    echo "all_name: $all_name"      #all_name: abcdefg.so.bak  
    echo "sub_name1: $sub_name1"    #sub_name1: abcdefg.so  
    echo "sub_name2: $sub_name2"    #sub_name2: ifconfig 

    九 printf命令

    printf 命令用于格式化输出, 是echo命令的增强版。它是C语言printf()库函数的一个有限的变形,并且在语法上有些不同。printf 不像 echo 那样会自动换行,必须显式添加换行符( )。

    这里仅说明与C语言printf()函数的不同:

    • printf 命令不用加括号
    • format-string 可以没有引号,但最好加上,单引号双引号均可。
    • 参数多于格式控制符(%)时,format-string 可以重用,可以将所有参数都转换。
    • arguments 使用空格分隔,不用逗号。

    下面的例子

    # format-string为双引号
    $ printf "%d %s
    " 1 "abc"
    1 abc
    # 单引号与双引号效果一样 
    $ printf '%d %s
    ' 1 "abc" 
    1 abc
    # 没有引号也可以输出
    $ printf %s abcdef
    abcdef
    # 格式只指定了一个参数,但多出的参数仍然会按照该格式输出,format-string 被重用
    $ printf %s abc def
    abcdef
    $ printf "%s
    " abc def
    abc
    def
    $ printf "%s %s %s
    " a b c d e f g h i j
    a b c
    d e f
    g h i
    j
    # 如果没有 arguments,那么 %s 用NULL代替,%d 用 0 代替
    $ printf "%s and %d 
    " 
    and 0
    # 如果以 %d 的格式来显示字符串,那么会有警告,提示无效的数字,此时默认置为 0
    $ printf "The first program always prints'%s,%d
    '" Hello Shell
    -bash: printf: Shell: invalid number
    The first program always prints 'Hello,0'
     

    十 if-else

    if 语句通过关系运算符判断表达式的真假来决定执行哪个分支。Shell 有三种 if ... else 语句:

    (1)if ... fi

        #!/bin/sh
        a=10
        b=20
        if [ $a == $b ]
        then
           echo "a is equal to b"
        fi
        if [ $a != $b ]
        then
           echo "a is not equal to b"
        fi

    运行结果: a is not equal to b

    (2)if ... else ... fi

        #!/bin/sh
        a=10
        b=20
        if [ $a == $b ]
        then
           echo "a is equal to b"
        else
           echo "a is not equal to b"
        fi

    运行结果: a is not equal to b

     

    (3)if ... elif  ... else ... fi

        #!/bin/sh
        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 of the condition met"
        fi
    运行结果: a is less than b
     

    (4)if ... else 语句也经常与 test 命令结合使用

        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

    运行结果: The two numbers are equal!          test 命令用于检查某个条件是否成立,与方括号[ ]类似。

     
     
     

    十一 case esac语句

    case ... esac 与其他语言中的 switch ... case 语句类似,是一种多分枝选择结构。case 语句匹配一个值或一个模式,如果匹配成功,执行相匹配的命令.case工作方式如上所示。取值后面必须为关键字 in,每一模式必须以右括号结束。取值可以为变量或常数。匹配发现取值符合某一模式后,其间所有命令开始执行直至 ;;。;; 与其他语言中的 break 类似,意思是跳到整个 case 语句的最后。取值将检测匹配的每一个模式。一旦模式匹配,则执行完匹配模式相应命令后不再继续其他模式。如果无一匹配模式,使用星号 * 捕获该值,再执行后面的命令。
     
    下面的脚本提示输入1到4,与每一种模式进行匹配:
        echo 'Input a number between 1 to 4'
        echo '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

    输入不同的内容,会有不同的结果,例如:

    Input a number between 1 to 4
    Your number is:3
    You select 3

    十二 for & while循环

    (1)for循环

        for loop in 1 2 3 4 5
        do
            echo "The value is: $loop"
        done
    运行结果:
    The value is: 1
    The value is: 2
    The value is: 3
    The value is: 4
    The value is: 5
     

     (2)while循环

        COUNTER=0
        while [ $COUNTER -lt 5 ]
        do
            COUNTER='expr $COUNTER+1'
            echo $COUNTER
        done
    运行结果:
    1
    2
    3
    4
    5
     
     
     

    十三  函数

    函数可以让我们将一个复杂功能划分成若干模块,让程序结构更加清晰,代码重复利用率更高。像其他编程语言一样,Shell 也支持函数。Shell 函数必须先定义后使用。
    Shell 函数的定义格式如下:
    function_name () {
        list of commands
        [ return value ]
    }

    如果你愿意,也可以在函数名前加上关键字 function.函数返回值,可以显式增加return语句;如果不加,会将最后一条命令运行结果作为返回值。
    Shell 函数返回值只能是整数,一般用来表示函数执行成功与否,0表示成功,其他值表示失败。如果 return 其他数据,比如一个字符串,往往会得到错误提示:“numeric argument required”。
    如果一定要让函数返回字符串,那么可以先定义一个变量,用来接收函数的计算结果,脚本在需要的时候访问这个变量来获得函数返回值。

    看一个例子:
        #!/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))
        }
        funWithReturn
        # Capture value returnd by last command
        ret=$?
        echo "The sum of two numbers is $ret !"

    运行结果:

    The function is to get the sum of two numbers...
    Input first number: 25
    Input another number: 50
    The two numbers are 25 and 50 !
    The sum of two numbers is 75 !

    函数返回值在调用该函数后通过 $? 来获得。

    十四 内置其他脚本

    . filename

    source filename

    两种方式的效果相同,简单起见,一般使用点号(.),但是注意点号(.)和文件名中间有一空格。

    十五 逐行读入文本

    #!/bin/bash
    # read line形式1
    cat xxx.txt | while read line
    do
            echo ${line}
    done
    
    
    # read line形式2
    while read line
    do
            echo ${line}
    done < xxx.txt
    
    # awk
    cat xxx.txt | awk '{print $0}'
     
     
     
  • 相关阅读:
    Codeforces Beta Round #92 (Div. 2 Only) B. Permutations 模拟
    POJ 3281 Dining 最大流 Dinic算法
    POJ 2441 Arrange the BUlls 状压DP
    URAL 1152 Faise Mirrors 状压DP 简单题
    URAL 1039 Anniversary Party 树形DP 水题
    URAL 1018 Binary Apple Tree 树形DP 好题 经典
    pytorch中的forward前向传播机制
    .data()与.detach()的区别
    Argparse模块
    pytorch代码调试工具
  • 原文地址:https://www.cnblogs.com/balfish/p/4679863.html
Copyright © 2011-2022 走看看