• shell(一)


    什么是shell

    • Shell(外壳) 是一个用 C 语言编写的程序,它是用户使用 Linux 的桥梁。Shell 既是一种命令语言又是一种程序设计语言
    • Shell 是指一种应用程序,这个应用程序提供了一个界面,用户通过这个界面访问操作系统内核的服务。

    • Shell属于内置的脚本,程序开发的效率非常高,依赖于功能强大的命令可以迅速地完成开发任务(批处理)

    常见的shell种类?

    在linux中有很多类型的shell,不同的shell具备不同的功能,shell还决定了脚本中函数的语法,Linux中默认的shell是/bin/bash(重点),流行的shell有ash、bash、ksh、csh、zsh等,不同的shell都有自己的特点以及用途。

    shell入门

    bash常见操作:

    • 常见快捷键:
      • ctrl+c   终止前台运行的程序 
        ctrl+d   退出 等价exit
        ctrl+l   清屏 
        ctrl+a   光标移到命令行的最前端          //编辑命令
        ctrl+e   光标移到命令行的后端            //编辑命令
        ctrl+u   删除光标前所有字符              //编辑命令
        ctrl+k   删除光标后所有字符              //编辑命令
        ctrl+r   搜索历史命令                   //命令需连续
    • 常见通配符:
      •   
        *:    匹配0或多个任意字符
        ?:    匹配任意单个字符
        [list]:    匹配[list]中的任意单个字符        //[abc]、[1-4]
        [!list]: 匹配除list中的任意单个字符
        {string1,string2,...}:匹配string1,string2或更多字符串
        #创建多个文件:touch {1..13}.jpg
    • $()和${}
      • $( )中放的是命令,相当于` `,例如todaydate=$(date +%Y%m%d)意思是执行date命令,返回执行结果给变量todaydate,也可以写为todaydate=`date +%Y%m%d`;
      • ${ }中放的是变量,例如echo ${PATH}取PATH变量的值并打印,也可以不加括号比如$PATH
    • bash中的引号:
      • 双引号"" :会把引号的内容当成整体来看待,允许通过$符号引用其他变量值
      • 单引号'' :会把引号的内容当成整体来看待,禁止引用其他变量值,shell中特殊符号都被视为普通字符
      • 反撇号`` :反撇号和$()一样,引号或括号里的命令会优先执行,如果存在嵌套,反撇号不能用

    使用流程:

    • 创建.sh文件
    • 编写shell代码

      #!/bin/bash
      #脚本第一行 , #!魔法字符,指定脚本代码执行的程序。即它告诉系统这个脚本需要什么解释器来执行,也就是使用哪一种Shell

      #以下内容是对脚本的基本信息的描述
      # Name: 名字
      # Desc:描述describe
      # Path:存放路径
      # Usage:用法
      # Update:更新时间

      #下面就是脚本的具体内容
      commands
      ...

    • 执行shell脚本 (chmod +x):脚本路径;/bin/bash 脚本路径,如果脚本没有权限,可以使用第二种方式执行

    shell进阶

    变量

    • 变量分为本地变量,环境变量,全局变量
      • 本地变量:当前用户自定义的变量。当前进程中有效,其他进程及当前进程的子进程无效。
      • 环境变量:当前进程有效,并且能够被子进程调用。
        • 查看当前用户的环境变量 //env
        • 查询当前用户的所有变量(临时变量与环境变量) //set
        • export //将当前变量变成环境变量,比如export a=1
      • 全局变量:全局所有的用户和程序都能调用,且继承,新建的用户也默认能调用.
        • $HOME/.bashrc             当前用户的bash信息(aliase、umask等)
          $HOME/.bash_profile       当前用户的环境变量
          $HOME/.bash_logout        每个用户退出当前shell时最后读取的文件
          /etc/bashrc               使用bash shell用户全局变量
          /etc/profile              系统和每个用户的环境变量信息
          
          /etc/profile——>$HOME/.bash_profile——>$HOME/.bashrc——>/etc/bashrc——>$HOME/.bash_logout
      • 系统变量(内置bash中变量) : shell本身已经固定好了它的名字和作用.
        • $#:脚本后面接的参数的个数
          $*:脚本后面所有参数,参数当成一个整体输出,每一个变量参数之间以空格隔开
          $@: 脚本后面所有参数,参数是独立的,也是全部输出
          $?:上一条命令执行后返回的状态,当返回状态值为0时表示执行正常,非0值表示执行异常或出错
           若退出状态值为0,表示命令运行成功
           若退出状态值为127,表示command not found
           若退出状态值为126,表示找到了该命令但无法执行(权限不够)
           若退出状态值为1&2,表示没有那个文件或目录
           
          $$:当前所在进程的进程号     echo $$   eg:kill -9 `echo $$`  = exit   退出当前会话
          $!:后台运行的最后一个进程号  (当前终端)  # gedit &
          !$    调用最后一条命令历史中的参数
          !!    调用最后一条命令历史
          $0:当前执行的进程/程序名  echo $0        
          $1~$9 位置参数变量
          ${10}~${n} 扩展位置参数变量(多位数要括起来,比如111,21,32)  第10个位置变量必须用{}大括号括起来
          
          了解$*和$@的区别:
          #!/bin/bash
          for i in "$@";do
          echo $i
          done
          
          echo "======我是分割线======="
          
          for i in "$*";do
          echo $i
          done

    变量相关操作

    1. 默认情况下,shell里定义的变量是不分类型的,可以给变量赋与任何类型的值;等号两边不能有空格,对于有空格的字符串做为赋值时,要用引号引起来
    
    变量名=变量值
    
    2. 变量的获取方式:    $变量名     ${变量名}    
    [root@server ~]# A=123456789
    [root@server ~]# echo $A
    123456789
    [root@server ~]# echo ${A:0:3}        //0代表从第1个字符开始截取,3代表截取3个字符
    123
    
    3. 取消变量:     unset  变量名(只读变量不可取消)
    4. 区分大小写,同名称但大小写不同的变量名是不同的变量  
    5. 变量名可以是字母或数字或下划线,但是不能以数字开头或者特殊字符
    6. 命令的执行结果可以保存到变量
    [root@server ~]# uname -r
    2.6.32-431.el6.x86_64
    [root@server ~]# kernel=`uname -r`
    [root@server ~]# echo $kernel
    2.6.32-431.el6.x86_64
    
    
    7. 数组
    数组定义:用括号来表示数组,数组元素用“空格”符号分割开。定义数组的一般形式为:
     array=(var1 var2 var3 var4)
    或者
    array[0]=v1
    array[1]=v2
    array[3]=v3
    
    读取数组:
    ${array [i]}  i表示元素
    使用@ 或 * 可以获取数组中的所有元素: 
    获取第一个元素
    echo ${user[0]}
    echo ${user[*]}        获取数组里的所有元素
    echo ${!array[@]}   获取数组元素的索引下标
    echo ${array[@]:1:2}    访问指定的元素
    [root@server ~]# echo ${user[@]}
    u1 u2 u3
    [root@server ~]# A=123456789
    [root@server ~]# echo ${A:3:4}
    4567
    [root@server ~]# echo ${user[@]:1:2}
    u2 u3
    
    举例:
    # for i in `echo ${user[*]}`;do echo "hello,$i";done
    
    8. 有类型变量 declare
    -i 将变量看成整数 
    -r 使变量只读  readonly
    -x 标记变量通过环境导出  export
    
    [root@server shell01]# a=10
    [root@server shell01]# b=20
    [root@server shell01]# c=$a+$b
    [root@server shell01]# echo $c
    10+20
    [root@server shell01]# 
    [root@server shell01]# declare -i a=10
    [root@server shell01]# declare -i b=20
    [root@server shell01]# declare -i c=$a+$b
    [root@server shell01]# echo $c
    30
    
    
    9. 交互式定义变量的值 read    主要用于让用户去定义变量值
    -p 提示信息
    -n 限制字符数 
    -s 不显示
    -t 超时(默认单位秒)
    
    10. 其他变量(扩展)
    1)取出一个目录下的目录和文件:dirname和 basename 
    2)变量"内容"的删除和替换
    一个“%”代表从右往左去掉一个/key/
    两个“%%”代表从右往左最大去掉/key/
    一个“#”代表从左往右去掉一个/key/
    两个“##”代表从左往右最大去掉/key/
    
    # A=/root/Desktop/shell/mem.txt 
    # echo $A
    /root/Desktop/shell/mem.txt
    # dirname $A   取出目录
    /root/Desktop/shell
    # basename $A  取出文件
    mem.txt
    # echo ${A%/*}   从右往左去掉“/*”内容
    /root/Desktop/shell
    # echo ${A%%.*} 从右往左最大长度去掉.后的内容
    /root/Desktop/shell/mem
    # echo ${A%%.txt}  从右往左最大长度去掉.txt内容
    /root/Desktop/shell/mem
    # echo ${A##/*/} 从左往右最大去掉所有"/*/"
    mem.txt
    # echo ${A#/*/}
    Desktop/shell/mem.txt
    
    //以下扩展内容自己练习完成
     1000  url=www.taobao.com
     1001  echo ${#url}     获取变量的长度
     1008  echo ${url#*.}
     1009  echo ${url##*.}
     1011  echo ${url%.*}
     1012  echo ${url%%.*}
     
    替换:/ 和 //
     1015  echo ${url/ao/AO}
     1017  echo ${url//ao/AO}   贪婪替换
     
    替代: - 和 :-  +和:+
     1019  echo ${abc-123}
     1020  abc=hello
     1021  echo ${abc-444}
     1022  echo $abc
     1024  abc=
     1025  echo ${abc-222}
    
    ${变量名-新的变量值} 或者 ${变量名=新的变量值}
    变量没有被赋值:会使用“新的变量值“ 替代
    变量有被赋值(包括空值): 不会被替代
    
     1062  echo ${ABC:-123}
     1063  ABC=HELLO
     1064  echo ${ABC:-123}
     1065  ABC=
     1066  echo ${ABC:-123}
    
    ${变量名:-新的变量值} 或者 ${变量名:=新的变量值}
    变量没有被赋值或者赋空值:会使用“新的变量值“ 替代
    变量有被赋值: 不会被替代
    
     1116  echo ${abc=123}
     1118  echo ${abc:=123}
    
    [root@server ~]# unset abc
    [root@server ~]# echo ${abc:+123}
    
    [root@server ~]# abc=hello
    [root@server ~]# echo ${abc:+123}
    123
    [root@server ~]# abc=
    [root@server ~]# echo ${abc:+123}
    
    ${变量名+新的变量值}
    变量没有被赋值或者赋空值:不会使用“新的变量值“ 替代
    变量有被赋值: 会被替代
    [root@server ~]# unset abc
    [root@server ~]# echo ${abc+123}
    
    [root@server ~]# abc=hello
    [root@server ~]# echo ${abc+123}
    123
    [root@server ~]# abc=
    [root@server ~]# echo ${abc+123}
    123
    ${变量名:+新的变量值}
    变量没有被赋值:不会使用“新的变量值“ 替代
    变量有被赋值(包括空值): 会被替代
    
    [root@server ~]# unset abc
    [root@server ~]# echo ${abc?123}
    -bash: abc: 123
    
    [root@server ~]# abc=hello
    [root@server ~]# echo ${abc?123}
    hello
    [root@server ~]# abc=
    [root@server ~]# echo ${abc?123}
    
    ${变量名?新的变量值}
    变量没有被赋值:提示错误信息
    变量被赋值(包括空值):不会使用“新的变量值“ 替代
    
    [root@server ~]# unset abc
    [root@server ~]# echo ${abc:?123}
    -bash: abc: 123
    [root@server ~]# abc=hello
    [root@server ~]# echo ${abc:?123}
    hello
    [root@server ~]# abc=
    [root@server ~]# echo ${abc:?123}
    -bash: abc: 123
    
    ${变量名:?新的变量值}
    变量没有被赋值或者赋空值时:提示错误信息
    变量被赋值:不会使用“新的变量值“ 替代
    
    说明:?主要是当变量没有赋值提示错误信息的,没有赋值功能

    只读变量(了解)

    #!/bin/bash
    a=1 readonly a a=2 #会报错
    只读变量不可删除,declare也可以

    流程控制语句

    #!/bin/bash
    #一个条件
    if condition
    then
        command
        ...
    fi
    
    #两个条件
    if condition
    then
        command
        ...
    else condition
        command
        ...
    fi
    
    
    #n个条件
    if condition1
    then
        command
        ...
    elif condition2
    then
        command
        ...
    else
        command
        ...
    fi

    条件判断

    格式1: test 条件表达式
    
    格式2: [ 条件表达式 ]
    
    格式3: [[ 条件表达式 ]] 支持正则 =~

    运算符

    在shell中,运算符和其他编程脚本语言一样,常见的有算数运算符、关系运算符、

    逻辑运算符、字符串运算符、文件测试运算符

    算数运算符

    运算符    说明                 举例
    +        加法                `expr $a + $b` 
    - 减法 `expr $a - $b`
    * 乘法 `expr $a * $b`
    / 除法 `expr $b / $a`
    % 取余 `expr $b % $a`
    = 赋值 a=$b == 相等。 [ $a == $b ]
    != 不相等。 [ $a != $b ]

    注意:

    • 条件表达式要放在方括号之间,并且要有空格,例如: [$a==$b] 是错误的,必须写成 [ $a == $b ]。
    • 原生bash不支持简单的数学运算,但是可以通过其他命令来实现,例如 awk 和 expr,expr 最常用。
    • 表达式和运算符之间要有空格,例如 2+2 是不对的,必须写成 2 + 2,这与我们熟悉的大多数编程语言不一样。
    • 完整的表达式要被 ` ` 包含,注意这个字符不是常用的单引号,在 Esc 键下边。

    关系运算符

    关系运算符只支持数字,不支持字符串,除非字符串的值是数字

    运算符         说明                                                    举例
    -eq        检测两个数是否相等,相等返回 true。                        [ $a -eq $b ]
    -ne        检测两个数是否相等,不相等返回 true。                      [ $a -ne $b ]
    -gt        检测左边的数是否大于右边的,如果是,则返回 true。           [ $a -gt $b ]
    -lt        检测左边的数是否小于右边的,如果是,则返回 true。           [ $a -lt $b ] 
    -ge        检测左边的数是否大于等于右边的,如果是,则返回 true。        [ $a -ge $b ] 
    -le        检测左边的数是否小于等于右边的,如果是,则返回 true。        [ $a -le $b ] 

    逻辑运算符

    运算符    说明                                                    举例
    !        非运算,表达式为 true 则返回 false,否则返回 true。          [ ! false ] 返回 true-o/||      或(或者)运算,有一个表达式为 true 则返回 true。           [ $a -lt 20 -o $b -gt 100 ] 返回 true-a/&&      与(并且)运算,两个表达式都为 true 才返回 true。           [ $a -lt 20 -a $b -gt 100 ] 返回 false
    逻辑判断符号:
    -a     &&  (and 逻辑与)
    -o     ||or 逻辑或)
     !   逻辑非
    [ 1 -eq 1 -a 1 -ne 0 ]
    [ 1 -eq 1 -o 1 -ne 1 ]

    [root@server shell01]# [ 1 -eq 0 ] && echo true || echo false
    false
    [root@server shell01]# [ 1 -eq 1 ] && echo true || echo false
    true


    优先级:
    -a(&&) > -o||> !

    字符串运算符

    运算符    说明                                        举例
    =        检测两个字符串是否相等,相等返回 true。        [ $a = $b ] 
    !=        检测两个字符串是否相等,不相等返回 true。     [ $a != $b ] 
    -z        检测字符串长度是否为0,为0返回 true。        [ -z $a ] 
    -n        检测字符串长度是否为0,不为0返回 true。      [ -n $a ]
    str        检测字符串是否为空,不为空返回 true。       [ $a ] 

    文件测试运算符

    文件测试运算符用于检测 Unix/Linux 文件的各种属性。

    操作符          说明                                                                           举例
    -b file        检测文件是否是块设备文件,如果是,则返回 true。                                     [ -b $file ] 
    -c file        检测文件是否是字符设备文件,如果是,则返回 true。                                   [ -c $file ] 
    -d file        检测文件是否是目录,如果是,则返回 true。                                          [ -d $file ] 
    -f file        检测文件是否是普通文件(既不是目录,也不是设备文件),如果是,则返回 true。              [ -f $file ] 
    -g file        检测文件是否设置了 SGID 位,如果是,则返回 true。                                  [ -g $file ] 
    -k file        检测文件是否设置了粘着位(Sticky Bit),如果是,则返回 true。                         [ -k $file ] 
    -p file        检测文件是否是有名管道,如果是,则返回 true。                                       [ -p $file ] 
    -u file        检测文件是否设置了 SUID 位,如果是,则返回 true。                                   [ -u $file ] 
    -r file        检测文件是否可读,如果是,则返回 true。                                            [ -r $file ] 
    -w file        检测文件是否可写,如果是,则返回 true。                                            [ -w $file ] 
    -x file        检测文件是否可执行,如果是,则返回 true。                                          [ -x $file ] 
    -s file        检测文件是否为空(文件大小是否大于0),不为空返回 true。                              [ -s $file ] 
    -e file        检测文件(包括目录)是否存在,如果是,则返回 true。                                  [ -e $file ] 
    
    

    示例

    示例:
    数值比较:
    [root@server ~]# [ $(id -u) -eq 0 ] && echo "the user is admin"
    [root@server ~]$ [ $(id -u) -ne 0 ] && echo "the user is not admin"
    [root@server ~]$ [ $(id -u) -eq 0 ] && echo "the user is admin" || echo "the user is not admin"
    
    
    类C风格的数值比较:
     1159  ((1==2));echo $?
     1160  ((1<2));echo $?
     1161  ((2>=1));echo $?
     1162  ((2!=1));echo $?
     1163  ((`id -u`==0));echo $?
     1209  ((a=123));echo $a
     1210  unset a
     1211  ((a==123));echo $?
     
    注意:在(( ))中,=表示赋值;==表示判断
    
    字符串比较:
    注意:双引号引起来,看作一个整体
     1196  a='hello world';b=world
     1197  [ $a = $b ];echo $?
     1198  [ "$a" = "$b" ];echo $?
     1199  [ "$a" != "$b" ];echo $?
     1200  [ "$a" !== "$b" ];echo $?        错误
     1201  [ "$a" == "$b" ];echo $?
     1202  test "$a" != "$b";echo $?
    
    注意:= 和 == 在 [ 字符串 ] 比较中都表示判断
    字符串一定要用“”
    
    思考:[ ] 和 [[ ]] 有什么区别?
    
     1213  a=
     1214  test -z $a;echo $?
     1215  a=hello
     1216  test -z $a;echo $?
     1217  test -n $a;echo $?
     1217  test -n "$a";echo $?
    
    # [ '' = $a ];echo $?
    -bash: [: : unary operator expected
    2
    # [[ '' = $a ]];echo $?
    0
    [[]]:可以比较为空

    1278 [ 1 -eq 0 -a 1 -ne 0 ];echo $? 1279 [ 1 -eq 0 && 1 -ne 0 ];echo $? 1280 [[ 1 -eq 0 && 1 -ne 0 ]];echo $?

    shell中sh, exec, source, fork, ./的区别




     

  • 相关阅读:
    使用Systemctl命令来管理系统服务
    使用lsblk命令列出系统中的块设备
    史上最全 | 1000余个实用尽调网站分类汇编
    ​2021年机器学习什么风向?谷歌大神Quoc Le:把注意力放在MLP上
    上手使用 DeepMind 分布式强化学习框架 Acme ,对开发者超友好
    005-ESP32学习开发(SDK)-新建工程补充-通过官方示例创建工程
    Golang 程序中实现优雅关闭 HTTP SERVER
    Golang的time.NewTicker周期性定时器使用案例
    彻底搞懂golang的GOROOT和GOPATH
    微服务之-ServiceMesh
  • 原文地址:https://www.cnblogs.com/ycg-blog/p/12746066.html
Copyright © 2020-2023  润新知