avatar

shell入门学习

什么是shell

参考视频
Shell是一个命令行解释器,它接受应用程序/用户命令,然后调用操作系统内核
Shell还是一个功能相当强大的编程语言,易编写,易调试,灵活性强

shell解析器

  • linux提供的解析器有
    [root@192 ~]# cat /etc/shells 
    /bin/sh
    /bin/bash
    /usr/bin/sh
    /usr/bin/bash
  • bash和sh的关系
    [root@192 bin]# cd /bin
    [root@192 bin]# ll | grep bash
    -rwxr-xr-x. 1 root root 964600 8月 8 2019 bash
    lrwxrwxrwx. 1 root root 10 4月 1 11:27 bashbug -> bashbug-64
    -rwxr-xr-x. 1 root root 6964 8月 8 2019 bashbug-64
    lrwxrwxrwx. 1 root root 4 4月 1 11:27 sh -> bash
    这里可以看出sh是调用的bash
  • Centos默认的解析器是bash
    [root@192 ~]# echo $SHELL
    /bin/bash

    Shell入门

    脚本格式

    脚本以#!/bin/bash开头(指定解析器)

    第一个Shell脚本

    创建一个shell脚本输出helloworld
  • 首先创建一个以sh为后缀的文件
    touch learnshell.sh #创建learnshell.sh文件
    vim learnshell.sh #编辑文件
    # 查看路径使用pwd命令可以输出全路径
  • 然后按下i进入编辑模式,写下echo “helloworld”,然后:wq退出
  • 使用sh命令运行脚本,然后我们就能看到输出了helloworld,这样我们的shell文件就可以运行了。
    [root@192 ~]# sh learnshell.sh
    helloworld

    第一种解析方式

    采用bash或sh+脚本的相对路径或绝对路径(不用赋予脚本+x权限)
    sh learn.sh
    bash learn.sh #这里路径可以是相对路径也可以是绝对路径,只要能找到就行

    第二种解析方式

    采用输入脚本的绝对路径或相对路径执行脚本(必须具有可执行权限+x)
    # 首先要赋予helloworld.sh 脚本的+x权限
    chmod 777 learnshell.sh
    #然后执行脚本
    ./learnshell.sh
  • 第一种执行方法,本质是bash解析器帮你执行脚本,所以脚本本身不需要执行权限。
  • 第二种执行方法,本质是脚本需要自己执行,所以需要执行权限。

    Shell脚本多命令处理

    多命令的意思就是多个命令在一个脚本中
    我们实现一个这样的功能:打开某个文件夹,创建一个文件,然后写入点东西
    #!/bin/bash
    cd /root/shelllearn
    touch test.txt
    echo "I love linux" >> test.txt
    这样运行以后我们就实现了在root得分shelllearn文件夹下创建一个test.txt文件内容为我爱linux

    Shell中的变量

    系统变量

  • 常用的系统变量:$HAME,$PWD,$SHELL,$USER
  • 使用方式
    # 查看系统中的变量
    echo $HAME
    # 查看shell中有哪些变量
    set

    自定义变量

  • 基本语法
    • 定义变量:变量名=值(中间没有空格,等号两边)
    • 撤销变量:unset 变量名
    • 声明静态变量:readonly 变量名,注意:不能被unset
  • 变量名定义规则
    • 变量名称可以是字母,数字和下划线组成,但是不能以数字开头,环境变量名称建议大写
    • 等号两侧不能有空格
    • 在bash中,变量默认类型都是字符串类型,无法直接进行数值计算
    • 变量的值如果有空格,需要使用双引号或者单引号括起来

      操作实例

  • 定义变量A
    A=5
    echo $A
  • 给变量A重新赋值
    A=8
    echo $A #直接对其进行赋值即可
  • 撤销变量A
    unset A
    echo $A #这样A就读不到了,因为已经撤销了
  • 声明静态变量,不能撤销
    readonly B=3
    echo $B #这样是能读到值的
    unset B #这样会报错,-bash: B: readonly variable
  • 变量如果有双引号,需要使用双引号或单引号括起来。并且在bash中,变量默认类型都是字符串类型,无法直接进行数值运算
    C=1+2
    echo $C #输出为1+2
    D=I love you #这样会报错 bash: world: command not found
    D="I love you"
    echo $D
  • 可把变量提升为全局环境变量,可供其他Shell程序使用:export 变量名
    B=2
    export B
    vim helloworld.sh
    在helloworld.sh文件中增加echo $B
    #!/bin/bash

    echo "helloworld"
    echo $B

    ./helloworld.sh # 如果没有加export文件时访问不到B的

    特殊变量

    $n

  • 基本语法:n为数字,$0代表该脚本的名称,$1-$9代表第一到第十个参数。十以上的参数需要用大括号来表示如${10}
  • 案例实操
    • 输出该脚本文件名称,输入参数1和输入参数2的值
      touch shellhello.sh #创建脚本
      vim shellhello.sh
      #!/bin/bash
      echo "$0,$1,$2"
      :wq #保存退出
      sh shellhello.sh "this" "is" #参数使用空格分割
      #输出结果为:shellhello.sh,this,is

      $#

  • 基本语法:获取所有输入参数的个数。常用于循环
  • 案例实操
    • 获取输入参数的个数
      touch shellhello.sh #创建脚本
      vim shellhello.sh
      #!/bin/bash
      echo "$#"
      :wq #保存退出
      sh shellhello.sh "this" "is" #参数使用空格分割
      #输出结果为:2

      $*,$@

  • 基本语法:
    • $:这个变狼代表命令行中所有的参数,$把所有的参数看成一个整体
    • $@:这个变量也代表命令行中所有的参数,不过$@把每个参数区分对待
  • 案例实操
    • 在shellhello.sh中输出这两个操作符看一下效果
      vim shellhello.sh
      #!/bin/bash
      echo "$*"
      echo "$@"
      :wq #保存退出
      sh shellhello.sh "this" "is" #参数使用空格分割
      #输出结果为:this is 输出了两遍

      $?

  • 基本语法:最后一次执行的命令返回的状态,如果这个变量的值为0,那么证明上一个命令正确执行;如果这个变量的值非0(具体是哪个数字由命令自己决定),则证明上一条命令执行不正确
  • 案例实操
    • 我们利用cd命令随便进入一个非法的目录,看看
      cd /test # 会报错
      echo "$?" #提示1,说明报错
      cd /usr #真是存在
      echo "$?" #提示0

      运算符

      $((y运算式))或者$[运算式]

      echo  $(((2+3)*4)) # 显示20
      echo $[(2+3)*4] # 显示20

      expr +,-,*,/,% 加,减,乘,除,取余

      ==注意:expr运算符间要有空格==
      expr 3 + 2 # 回车输出5
      expr 3+4 或者expr 3 +4都会报错
      #计算(2+3)*4
      expr `expr 3 + 2` \* 4 #这种运算需要嵌套,这个嵌套的点是键盘左上角的在1旁边的按键

      条件判断

  • 基本语法:[ condition ] 注意:condition前后都要有空格
    注意:条件非空即为true,[ atguigu ]返回true,[] 返回false。

    常用判断条件

    两个整数之间的比较

  • = 字符串比较
  • -lt 小于(less than)
  • -le 小于等于(less equal)
  • -eq 等于(equal)
  • -gt 大于(greater than)
  • -ge 大于等于(greater equal)
  • -ne 不等于(Not equal)

    按照文件权限进行判断

  • -r 有读文件的权限(read)
  • -w 有写文件的权限(write)
  • -x 有执行的权限(execute)

    按照文件类型进行判断

  • -f 文件存在并且是一个常规的文件(file)
  • -e 文件存在(existence)
  • -d 文件存在并是一个目录(directory)

    多条件判断

    && 表示前一条命令执行成功时,才执行后一条命令,|| 表示上一条命令执行失败后,才执行下一条命令
    [ 22 -ge 34 ] && echo "hello" #不会输出任何东西
    [ 22 -ge 34 ] || echo "hello" #输出hello

    流程判断

    if判断

  • 基本语法
    #第一种方式
    if [ 条件表达式 ];then
    #程序写在这里
    fi
    # 第二种方式
    if [ 条件表达式 ]
    then
    # 程序
    fi
    注意事项
  • [ 条件判断式 ],中括号和条件判断式之间必须有空格
  • if后面必须有空格

    实例

    根据传入的参数,实现输出日志
    if [ $1 -eq 1 ];then
    echo "我真帅"
    elif [ $1 -eq 2 ] #这是if else
    then "我不帅"
    fi

    case语句

  • 基本语法
    case $变量名 in
    "值1")
    如果变量的值等于值1,则执行程序1
    ;;
    "值2")
    如果变量的值等于值2,则执行程序2
    ;;
    *)
    如果变量的值都不是以上的值,则执行该程序
    ;;
    esac
  • 注意事项
    • case行尾必须为单词“in”,每一个模式匹配必须以右括号“)”结束。
    • 双分号“;;”表示命令序列结束,相当于java中的break。
    • 最后的“*)”表示默认模式,相当于java中的default。

      实例

      输入1,传出haha;输入2,传出xixi,如果是其他返回error
      case $1 in
      1) echo "haha"
      ;;
      2) echo "xixi"
      ;;
      *) echo "error"
      ;;
      esac

      for循环

  • 基本语法1
    for (( 初始值;循环控制条件;变量变化 ))
    do
    #编写程序
    done
  • 基本语法2
    for 变量 in 值1 值2 值3
    do
    #程序编写
    done

    案例

    #版本1: 从1加到100
    s=0
    for((i=1;i<=100;i++))
    do
    s=$[$s+$i]
    done
    echo "$s"
    #版本2 :打印输入的所有的参数
    for a in $@ #这里如果用$*效果一样,但是如果用"$@"和"$*"后者输出整体,前者还是分离
    do
    echo $a
    done

    while循环

  • 基本语法
    while [ 条件表达式 ]
    do
    #编写程序
    done
  • 实例
    s=0
    i=1
    while [ $i -le 100 ]
    do
    s=$[$s+$i]
    i=$[$i+1]
    done
    echo $s

    read读取控制台输入

    基本语法

  • read(选项)(参数)
  • 选项:
    • -p:指定读取值时的提示符;
    • -t:指定读取值时等待的时间(秒)。
  • 参数
    • 变量:指定读取值的变量名

      实例操作

      read -t 7 -p "Enter your name in 7 seconds " name
      echo $name

      函数

      系统函数

      basename

  • 基本语法
    basename[string/pathname][suffix]:basename命令会删除所有的前缀包括最后一个(‘/‘)字符,然后将字符串显示出来
  • 选项:
    • suffix是后缀,如果suffix被指定了,basename会将payhname或string中的suffix去掉
  • 案例实操
    #这句话返回的结果是test.txt
    basename /home/testshell/test.txt
    #这句话返回的结果是test
    basename /home/testshell/test.txt .txt

    dirname

    dirname 文件绝对路径:从给定的包含绝对路径的文件夹中取出文件名(非目录的部分),然后返回剩下的路径(目录的部分)
  • 操作
    dirname /home/testshell/test.txt
    #/home/testshell 除去文件名的路径字符串
    还有很多系统函数,这里简单介绍两个常用的(其他系统函数我也不知道在哪看23333,没有找到其他的)

    自定义函数

    基本语法

    [ function ] funname[()]
    {
    Action
    [return int;]
    }
    funname
  • 必须在调用函数地方之前,先声明函数,==shell脚本是逐行运行==。不会像其它语言一样先编译。
  • 函数返回值,只能通过$?系统变量获得,可以显示加:return返回,如果不加,将以最后一条命令运行结果,作为返回值。return后跟数值n(0-255)

    案例

    #!/bin/bash
    function sum()
    {
    s=0
    s=$[ $1 + $2 ]
    echo "$s"
    }

    read -p "Please input the number1: " n1;
    read -p "Please input the number2: " n2;
    sum $n1 $n2;

    Shell工具

    cut

    在文件中负责剪切数据用的,cut命令从文件的每一行剪切字节,字符,和字段并将这些字节字段,字符输出
  • 基本用法 cut[选项参数] filename
    说明,默认分隔符是制表符
  • 选项参数说明
    • -f 列号,提取第几列
    • -d 分隔符,按照指定分隔符分割列
  • 案例
    • 数据准备
      touch cut.txt
      vim cut.txt
      dong shen
      guan zhen
      wo wo
      lai lai
      le le
    • 切割cut.txt第一列
      cut -d " " -f 1 cut.txt 
      dong
      guan
      wo
      lai
      le
    • 切割cut.txt第二、三列
      cut -d " " -f 2,3 cut.txt 
      shen
      zhen
      wo
      lai
      le
    • 在cut.txt文件中切割出guan
      cat cut.txt | grep "guan" | cut -d " " -f 1
      guan
    • 选取系统PATH变量值,第2个“:”开始后的所有路径:
      echo $PATH
      /usr/lib64/qt-3.3/bin:/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/sbin:/home/atguigu/bin

      echo $PATH | cut -d : -f 2-
      /usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/sbin:/home/atguigu/bin
    • 切割ifconfig 后打印的IP地址
      ifconfig eth0 | grep "inet addr" | cut -d : -f 2 | cut -d " " -f 1
      192.168.1.102

      sed

      sed是一种流编辑器,它一次处理一行内容。处理时,把当前处理的行存储在临时缓冲区中,称为“模式空间”,接着用sed命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕。接着处理下一行,这样不断重复,直到文件末尾。文件内容并没有改变,除非你使用重定向存储输出。

      基本用法

      sed [选项参数] ‘command’ filename
  • 参数说明
    • -e 直接在指令列表上进行sed的动作编辑
  • 命令功能描述
    • a 新增,a的后面可以接字符串,在下一行出现
    • d 删除
    • s 查找并替换
    • 还有很多

      案例实操

  • 数据准备
    touch sed.txt
    vim sed.txt
    shan bei
    dong jing
    wo wo
    lai lai
    le le
  • 将”mei nv”这个单词插到sed.txt第二行,打印
    sed "2a mei nv" sed.txt #如果a前面不加2,那么就会在该文本的每一行都增加mei nv
    #显示为
    #shan bei
    #dong jing
    #mei nv
    #wo wo
    #lai lai
    #le le
    cat sed.txt #文件本身没有增加
  • 删除sed.txt文件所有包含wo的行
    sed '/wo/d' sed.txt
  • 将sed.txt文件中wo替换为ni
    sed 's/wo/ni/g' sed.txt     #g代表global,全部替换
  • sed一次执行多个命令,利用-e进行分割
    sed -e "2d" -e 's/wo/ni/g' sed.txt

    awk

    一个强大的文本分析工具,把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行分析处理。

    基本用法

    awk [选项参数] ‘pattern1{action1} pattern2{action2}…’ filename
  • pattern:表示AWK在数据中查找的内容,就是匹配模式
  • action:在找到匹配内容时所执行的一系列命令

    选项参数说明

  • -F :指定输入文件拆分隔符
  • -v : 赋值一个用户定义变量
    还有很多参数,这里只介绍这两个,剩下的可以慢慢的发掘

    awk的内置变量

  • FILENAME : 文件名
  • NR : 已读的记录数(行号)
  • NF : 浏览记录的域的个数(切割后,列的个数,列号)

    案例实操

  • 获取数据
    sudo cp /etc/passwd ./
    #用passwd文件进行操作,复制到当前目录
  • 搜索passwd文件以root关键字开头的所有行,并输出该行的第7列。
    awk -F : '/^root/{print $7}' passwd # awk 按照:进行分割,然后找到root开头的并且打印第七行  /^root/是一个正则
  • 搜索passwd文件以root关键字开头的所有行,并输出该行的第1列和第7列,中间以“,”号分割。
    awk -F : '/^root/{print $1","$7}' passwd
    只有匹配了pattern的行才会执行action
  • 只显示/etc/passwd的第一列和第七列,以逗号分割,且在所有行前面添加列名user,shell在最后一行添加”zenshin,/bin/zuishuai”。
    awk -F : 'BEGIN{print "user, shell"} {print $1","$7} END{print "dahaige,/bin/zuishuai"}' passwd
    BEGIN 在所有数据读取行之前执行;END 在所有数据执行之后执行。
  • 将passwd文件中的用户id增加数值1并输出
    awk -v i=1 -F: '{print $3+i}' passwd
  • 统计passwd文件名,每行的行号,每行的列数
    awk -F : '{print "filename:"  FILENAME ", linenumber:" NR  ",columns:" NF}' passwd
  • 切割IP
    ifconfig eth0 | grep "inet addr" | awk -F : '{print $2}' | awk -F " " '{print $1}'
  • 查询sed.txt中空行所在的行号
    awk '/^$/{print NR}' sed.txt

    sort

    sort命令是在Linux里非常有用,它将文件进行排序,并将排序结果标准输出。

    基本语法

    sort(选项)(参数)
    选项 说明
    -n 依照数值的大小排序
    -r 以相反的顺序来排序
    -t 设置排序时所用的分隔字符
    -k 指定需要排序的列
    #### 操作
  • 准备数据
    touch sort.sh
    vim sort.sh
    bb:40:5.4
    bd:20:4.2
    xz:50:2.3
    cls:10:3.5
    ss:30:1.6
  • 按照“:”分割后的第三列倒序排序。
    sort -t : -nrk 3  sort.sh  #按照:进行切割,nrk 3 是指按照第三列的数值倒序排序

    企业真题

    京东

  • 使用Linux命令查询file1中空行所在的行号
    awk '/^$/{print NR}' sed.txt
  • 有文件chengji.txt内容如下:张三 40 李四 50 王五 60 使用Linux命令计算第二列的和并输出
    cat chengji.txt | awk -F " " '{sum+=$2} END{print sum}'

    搜狐&和讯网

  • Shell脚本里如何检查一个文件是否存在?如果不存在该如何处理?
    #!/bin/bash

    if [ -f file.txt ]; then
    echo "文件存在!"
    else
    echo "文件不存在!"
    fi

    新浪

  • 用shell写一个脚本,对文本中无序的一列数字排序
    sort -n test.txt|awk '{a+=$0;print $0}END{print "SUM="a}'

    金和网络

  • 请用shell脚本写出查找当前文件夹(/home)下所有的文本文件内容中包含有字符”shen”的文件名称
    grep -r "shen" /home | cut -d ":" -f 1

到目前位置,shell算是简单的入门了,还有许多知识需要去学习

文章作者: zenshin
文章链接: https://zlh.giserhub.com/2020/04/04/cl35o0mqd002bp4tgablb8dye/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 zenshin's blog
打赏
  • 微信
    微信
  • 支付宝
    支付宝

评论