美文网首页
Linux shell编程

Linux shell编程

作者: 宏势 | 来源:发表于2022-04-02 15:38 被阅读0次

    什么shell

    shell 是用户与linux通讯的桥梁,既是一种命令语言,也是一种程序设计语言。我们经常说的shell脚本就是用shell编写的程序。

    Shell种类

    #查看当前服务器支持shell
    cat /etc/shells 或者 chsh -l
    #查看当前服务器默认shell
    echo $SHELL
    

    当前大多数linux系统默认使用/bin/bash,/usr/sbin/nologin(/sbin/nologin)

    • Bourne Again Shell(/bin/bash)最常用的,默认值
    • Bourne Shell(/usr/bin/sh或/bin/sh)Unix最早使用的shell,已被/bin/bash取代
    • C Shell(/bin/csh)被/bin/tcsh所取代
    • TC Shell (/bin/tcsh) /bin/csh的增强版
    • Tmux(/usr/bin/tmux) 终端复用软件
    • K Shell(/bin/ksh)

    运行环境

    打开文本编辑器,扩展名为sh,解释执行,支持两种运行方式

    • 可执行程序执行
      vim /test.sh
      #脚本文件第一行指定解释器 
      #!/bin/bash
      echo hello world!
      
      chmod +x tes.sh #增加可执行权限
      ./test.sh #当前目录执行
      
    • 作为解释器参数
      会忽略脚本里面的第一行指定的解释器
      /bin/bash test.sh

    数据类型

    shell脚本基础数据类型只支持数字类型和字符串,不支持布尔类型

    变量

    str="Linux shell编程" 
    num=100
    echo ${str} #读取变量用$,大括号可选,主要用于识别变量的边界
    echo $num
    
    #通过命令语句赋值变量
    for file in `ls /etc`
    do
      echo ${file}
    done
    #或者
    for file in $(ls /etc)
    do
     echo ${file}
    done
    
    # 只读变量
    readonly readonly_str="Linux shell 编程"
    readonly_str="修改Linux shell编程"  #会报错,不允许修改
    unset readonly_str #会报错
    
    #删除变量
    str="Linux shell 编程"
    unset str #删除变量,变量为空
    str="新 Linux shell 编程"  #从新声明变量
    echo $str
    

    变量复制等号前后不能有空格,使用readonly设置成只读变量,只读变量不能删除

    单引号和双引号区别

    • 单引号里的任何字符都会原样输出,单引号字符串中的变量是无效的,不支持转义字符;

    • 单引号字串中引号成对出现,作为字符串拼接使用

    • 双引号里可以有变量

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

    say='welcome'
    str='Linux shell编程${say}'
    str1='Linux shell编程'${say}''
    str2="Linux shell编程${say}"
    str3="Linux shell编程\"${say}\""
    echo $str  $str1
    echo $str2
    echo $str3
    #输出结果
    Linux shell编程${say}
    Linux shell编程welcome 
    Linux shell编程welcome 
    Linux shell编程"welcome"
    

    浮点型运算采用bc或者awk处理,示例如下:

    result=$(echo "5.01-4*2.0"|bc)
    echo $result
    result=$(awk 'BEGIN{print 7.01*5-4.01 }')
    echo $result
    

    字符串

    • 获取字符串长度
    str="abcdefg"
    echo ${#str}  
    
    • 截取字符串
    str="abcdefg"
    echo ${str:3}  #输出defg   从i=3开始截取
    echo ${str:2:3}   #输出cde  从i=2开始截取3个字符
    echo ${str:0-4:2} #输出de 从右边第4个字符开始,截取2个字符
    
    • 按字符内截取
    net=https://www.jianshu.com/u/86f7ba800fed
    
    #1. #*/ 表示从左边开始,删除第一个/和左边的字符
    echo ${net#*/} #/www.jianshu.com/u/86f7ba800fed
    
    #2. ##*/ 表示从左边开始,删除最后一个/和左边的字符
    echo ${net##*/} #86f7ba800fed
    
    #3. %/* 表示从右边开始,删除第一个/和右边的字符删
    echo ${net%/*} #https://www.jianshu.com/u
    
    #4. %%/* 表示从右边开始,删除最后一个/和右边的字符删
    echo ${net%%/*} #https:
    

    具体更复杂的字符串操作可以参考awk,sed, expr,cut等命令

    数组

    只支持一维数组,元素之间用空格分隔,array_name=(value1 value2 ... valuen),元素可以字符串也可以数字

    array=("val1" "val2" 10 11)
    array[4]=12
    array[10]=100
    echo "数组长度为${#array[*]},${#array[@]}"  #获取数组长度
    
    #遍历数组
    for val in ${array[*]} #获取数组所有元素
    do
        echo "数组元素值为:${val}"
    done
    

    运算符

    原生bash不支持简单的数学运算,需通过(()),[],let或者expr实现, 算数运算如下:

    a=10;b=20
    val=`expr $a + $b`  // val=$((a+b)) 或val=$[a+b] 或者let val=a+b
    echo "a + b : $val"
    
    val=`expr $a - $b`
    echo "a - b : $val"
    
    val=`expr $a \* $b`
    echo "a * b : $val"
    
    val=`expr $b / $a`
    echo "b / a : $val"
    
    val=`expr $b % $a`
    echo "b % a : $val"
    
    if [ $a == $b ]
    then
       echo "a 等于 b"
    fi
    if [ $a != $b ]
    then
       echo "a 不等于 b"
    fi
    

    乘号(*)前边必须加反斜杠()才能实现乘法运算;运算符和中括号前后必须有空格,例如[$a==$b] 是错误的,必须写成 [ $a == $b ]

    关系运算符只支持数字,不支持字符串,除非字符串的值是数字
    假设a为10,b为20

    运算符 说明 举例
    -eq 相等返回true [ $a -eq $b ] 返回false
    -ne 不相等返回true [ $a -ne $b ] 返回true
    -gt 左边大于右边true [ $a -gt $b ] 返回false
    -lt 左边小于右边true [ $a -lt $b ] 返回true
    -ge 大于等于返回true [ $a -ge $b ] 返回false
    -le 小于等于返回true [ $a -le $b ] 返回true

    布尔运算符,假设变量a为10,b为20

    运算符 说明 举例
    非运算符 [ ! $a -gt $b] 返回true
    -o 或运算符 [ $a -lt 20 -o $b -gt 100 ] 返回 true
    -a 与运算符 [ $a -lt 20 -a $b -gt 100 ] 返回 false

    逻辑运算符 假设变量a为10,b为20

    运算符 说明 举例
    && 逻辑AND [[ $a -lt 20 && $b -gt 100 ]] 返回 false
    || 逻辑OR [[ $a -lt 20 || $b -gt 100 ]] 返回 true

    逻辑运算符多了一个中括号[]

    字符串运算符

    a="abc";b="efg"
    
    if [ $a = $b ]  #判断字符串是否相等   [ $a != $b ]  判断字符串不相等
    then
       echo "$a = $b : a 等于 b"
    else
       echo "$a = $b: a 不等于 b"
    fi
    if [ $a ] #判断字符串不为空(true)
    then
       echo "$a : 字符串不为空"
    else
       echo "$a : 字符串为空"
    fi
    if [ -z $a ]  #判断字符串长度为0(true)  [ -n "$a" ]  判断字符串长度不为0(true)
    then
       echo "-z $a : 字符串长度为 0"
    else
       echo "-z $a : 字符串长度不为 0"
    fi
    
    

    文件测试运算符

    file="/var/www/test.sh"
    if [ -r $file ]  #判断文件是否可读,  [ -w $file ] 是否可写,[ -x $file ]是否可执行
    then
       echo "文件可读"
    else
       echo "文件不可读"
    fi
    
    if [ -e $file ] #判断文件是否存在  [ -s $file ]文件是否为空
    then
       echo "文件存在"
    else
       echo "文件不存在"
    fi
    
    if [ -f $file ]  #判断是否为普通文件(既不是目录,也不是设备文件) [ -d $file ]是否是目录
    then
       echo "文件为普通文件"
    else
       echo "文件为特殊文件"
    fi
    
    
    

    流程控制

    • if else fi
    a=10;b=20
    if [ $a == $b ]
    then
       echo "a 等于 b"
    elif [ $a -gt $b ]
    then
       echo "a 大于 b"
    elif [ $a -lt $b ]
    then
       echo "a 小于 b"
    else
       echo "没有符合的条件"
    fi
    
    • for 循环
    for((i=0;i<10;i++))
    do
        echo "index:$i"
    done
    
    for var in "index1" "index2" "index3" "index4" "index5"
    do
        echo "$var"
    done
    
    • case ...esac
    code="shell"
    
    case "$code" in
      "java") echo "最喜欢java"
       ;;
       "shell") echo "最喜欢shell"
       ;;
       "go") echo "最喜欢go"
       ;;
       "*") echo "都喜欢"   #匹配不到执行该语句
       ;;
    esac
    
    • while 语句
    num=1
    while(( $num<=5 ))
    do
        echo $num
        num= `expr $num + 1`  # let "int++"
    done
    

    break终止结束循环;continue指的是本次的循环,进入下一次的循环

    函数

    • 函数不带任何参数, 可以省略关键字function
    • 调用函数可以传递任意个数参数,函数内通过$n形式获取
    • 函数返回,可以显示return返回,如果不加以最后一条命令运行结果作为返回值,且只能返回整数,0表示成功,其它值表示失败,建议显示return
    • 函数返回不能赋值,所以一般通过函数内赋值给全局变量来获取返回值
    funWithParam(){
        echo "第一个参数为 $1 !"   
        echo "第二个参数为 $2 !"
        echo "第十个参数为 $10 !"
        echo "第十个参数为 ${10} !"
        echo "第十一个参数为 ${11} !"
        echo "参数总数有 $# 个!"
        echo "作为一个字符串输出所有参数 $* !"
    }
    funWithParam 1 2 3 4 5 6 7 8 9 34 73
    
    function add(){
       echo "执行相加操作"
       return   `expr  $1 +  $2`
    }
    function reduce(){
        echo "执行相减操作"
        expr  $1 -  $2
    }
    add 10 20;echo $? ;echo $?
    #result=add 30 50  会报错
    reduce 100 20;echo $? ;echo $?
    
    

    输出结果如下:

    执行相加操作
    30
    0
    执行相减操作
    80
    0
    0
    

    输入/输出重定向

    一般情况下,每个 Unix/Linux 命令运行时都会打开三个文件:

    • 标准输入文件(stdin):stdin的文件描述符为0,Unix程序默认从stdin读取数据。
    • 标准输出文件(stdout):stdout 的文件描述符为1,Unix程序默认向stdout输出数据。
    • 标准错误文件(stderr):stderr的文件描述符为2,Unix程序会向stderr流中写入错误信息。
    echo "Linux shell编程" > test.txt
    #往test.txt追加字符串
    echo "Linux shell编程" >> test.txt 
    
    # 统计test.txt 的行数
    wc -l < test.txt
    

    2>&1 stdout与stderr合并,>号前后不能有空格

    #stderr重定向到test.txt
    echo "Linux shell编程"  2> test.txt
    
    #stdout 和 stderr 合并后重定向到 file
    echo "Linux shell编程"  > test.txt 2>&1
    
    #输出重定向到/dev/null,达到“禁止输出”效果,即结果不会输出到屏幕上
    echo "Linux shell编程"  > /dev/null
    
    #同时屏蔽 stdout 和 stderr
    echo "Linux shell编程"  > /dev/null 2>&1
    
    

    << tag 将开始标记 tag 和结束标记 tag 之间的内容作为输入
    创建文件并写入内容例子如下:

    cat > test.txt<<EOF
    欢迎学习
    Linux shell编程
    EOF
    

    文件包含

    文件包含主要用于提取一些公共脚本,支持两种方式:
    source ./basic.sh 或者 . ./basic.sh(注意点号(.)和文件名中间有一空格)

    vim basic.sh

    #!/bin/bash
    str="Linux shell编程"
    

    vim test.sh

    #!/bin/bash
    source ./basic.sh #或者../basic.sh
    echo $str
    

    shell 语法相对比较单一,只支持数字和字符串基础类型;扩展类型只支持函数和数组,函数返回值只支持数字,不能赋值给变量;算术运算需引入expr或者awk,-gt 代替 > 比较,条件表达式[] 及运算符前后要有空格,变量赋值等号前后不能空格,分号的作用跟换行是一样的

    相关文章

      网友评论

          本文标题:Linux shell编程

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