• Shell编程



      
      
      

      

    Shell脚本入门

      

      

    (1) 脚本格式:

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


    练习:
    创建一个Shell脚本,输出 hello world

    PS:vim功能很强大,如果有文件就直接打开,如果没文件就创建并打开。

    终端输入:

    [root@hadoop100 scripts]# vim hello.sh

    按i进入编辑模式,文件里输入:

    #!/bin/bash
    echo "hello world"
    
    • 1
    • 2

    按Esc退出编辑模式,按 :wq 保存并退出。

      

    (2) 脚本执行:

    • 第一种:采用 bashsh +脚本的相对路径或绝对路径 (不用赋予脚本 +x 权限)

      bash+脚本的相对路径:

    [root@hadoop100 scripts]# bash hello.sh
    hello,world

      bash+脚本的绝对路径:

    [root@hadoop100 scripts]# bash /root/scripts/hello.sh
    hello,world

      sh+脚本的相对路径:

    [root@hadoop100 scripts]# sh hello.sh
    hello,world

      sh+脚本的绝对路径:

    [root@hadoop100 scripts]# sh /root/scripts/hello.sh
    hello,world

    • 第二种:直接输入脚本的绝对路径或相对路径(必须赋予脚本 +x 可执行权限)

    PS:r是读权限,w是写权限,x是可执行权限。一般刚创建的文件只有rw权限,没有x权限,x权限那里是个 -

      ①首先要赋予脚本 +x 权限

    [root@hadoop100 scripts]# chmod +x hello.sh

      ②执行脚本

      相对路径

    [root@hadoop100 scripts]# ./hello.sh
    hello,world

      绝对路径:

    [root@hadoop100 scripts]# /root/scripts/hello.sh
    hello,world


    知识拓展:

    1. 这两种方法都是在当前 shell 中打开一个子 shell 来执行脚本内容,当脚本内容结束,则子 shell关闭,回到父 shell 中。(存在环境变量继承问题:如在子 shell 中设置的当前变量,父 shell 是不可见的)
    2. 第一种执行方法本质是bash解析器执行脚本,所以脚本本身不需要执行权限。第二种执行方法本质是脚本需要自己执行,所以需要执行权限。
    3. pwd 查看目录 ; mkdir 创建文件夹 ; touch 新建文件 ; cat 查看内容

      
      
      

      

    变量

      

      

    一、系统预定义变量

      
    (1) 常用的系统变量:

    $HOME(当前主目录)、$PWD(当前工作目录目录)、$SHELL(当前使用的shell解析器)、$USER(当前用户)等。

      
    (2) 练习:

    [root@hadoop100 scripts]# echo $HOME
    /root
    [root@hadoop100 scripts]# echo $PWD
    /root/scripts
    [root@hadoop100 scripts]# echo $SHELL
    /bin/bash
    [root@hadoop100 scripts]# echo $USER
    root

    [root@hadoop100 scripts]# ls $HOME
    initial-setup-ks.cfg scripts 公共 模板 视频 图片 文档 下载 音乐 桌面

      

    二、自定义变量

      
    (1) 基本语法:

    1. 定义变量: 变量名=变量值 (注意:=号前后都不能有空格!!!)
    2. 撤销变量: unset 变量名
    3. 声明静态变量: readonly 变量 (注意:不能 unset)
    4. 声明全局变量: export 变量

      
    (2) 变量定义规则:

    1. 变量名称可以由字母、数字和下划线组成,但是不能以数字开头,环境变量名建议大写。
    2. = 等号两侧不能有空格。
    3. 在 bash 中,变量默认类型都是字符串类型,无法直接进行数值运算。
    4. 变量的值如果有空格,需要使用双引号或单引号括起来。

      
    (3) 练习:

    [root@hadoop100 scripts]# a=10
    [root@hadoop100 scripts]# echo $a
    10
    [root@hadoop100 scripts]# unset a
    [root@hadoop100 scripts]# echo $a

    unset后,echo就打印空白一行了。

      

    三、特殊变量

      

    1、 $n

      
    (1) 基本语法:

      $n —— 位置参数
    功能描述:n 为数字,$0 代表该脚本的名称,$1-$9 代表第一到第九个参数,十以上的参数需要用大括号包含,如 ${10} 。

      
    (2) 练习:

    !#/bin/bash
    echo '=================$n==================='
    echo script name: $0
    echo 1st parameter: $1
    echo 2nd parameter: $2
    
    • 1
    • 2
    • 3
    • 4
    • 5

    [root@hadoop100 scripts]# ./parameter.sh abc def
    =================$n===================
    script name: ./parameter.sh
    1st parameter: abc
    2nd parameter: def

      

    2、 $#

      
    (1) 基本语法:

      $# —— 参数个数统计变量
    功能描述:获取所有输入参数个数,常用于循环,判断参数的个数是否正确以及加强脚本的健壮性。

      
    (2) 练习:

    !#/bin/bash
    echo '=================$n==================='
    echo script name: $0
    echo 1st parameter: $1
    echo 2nd parameter: $2
    echo '=================$#==================='
    echo parameter numbers: $#
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    [root@hadoop100 scripts]# ./parameter.sh abc def
    =================$n=================
    script name: ./parameter.sh
    1st parameter: abc
    2nd parameter: def
    =================$#=================
    parameter numbers: 2

      

    3、 $*、$@

      
    (1) 基本语法:

      $* —— 获取当前命令行提供的所有参数
    功能描述:获取当前命令行提供的所有参数,$*把所有参数看成一个整体。

      $@ —— 获取当前命令行提供的所有参数
    功能描述:获取当前命令行提供的所有参数,$@把每个参数区分对待。

      
    (2) 练习:

    !#/bin/bash
    echo '=================$n==================='
    echo script name: $0
    echo 1st parameter: $1
    echo 2nd parameter: $2
    echo '=================$#==================='
    echo parameter numbers: $#
    echo '=================$*==================='
    echo $*
    echo '=================$@==================='
    echo $@
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    [root@hadoop100 scripts]# ./parameter.sh abc def
    =================$n=================
    script name: ./parameter.sh
    1st parameter: abc
    2nd parameter: def
    =================$#=================
    parameter numbers: 2
    =================$*===================
    abc def
    =================$@===================
    abc def

    区别在循环中可以看到。

      

    4、 $?

      
    (1) 基本语法:

      $? —— 整个脚本的返回值
    功能描述:最后一次执行的命令的返回状态。如果这个变量的值为0,证明上一个命令正确执行;如果这个变量的值为非0(具体是哪个数,由命令自己决定,但有个范围:0~255),则证明上一个命令执行不正确了(如果用在函数里也可以表示函数的返回值,但要注意范围)。

      
    (2) 练习:

    [root@hadoop100 scripts]# ./hello.sh
    hello,world
    [root@hadoop100 scripts]# echo $?
    0

      
      
      

      

    运算符

      

      
    (1) 基本语法:

       $((运算式))$[运算式]

      
    (2) 练习:

    [root@hadoop100 scripts]# echo $((5+2))
    7
    [root@hadoop100 scripts]# echo $[5*2]
    10

    [root@hadoop100 scripts]# a=$[(2+3)*4]
    [root@hadoop100 scripts]# echo $a
    20

      
    (3) 进阶练习:

    编写个两数相加的文件

    #!/bin/bash
    sum=$[$1+$2]
    echo sum=$sum
    
    • 1
    • 2
    • 3

    [root@hadoop100 scripts]# ./add.sh 25 90
    sum=115

      
      
      

      

    条件判断

      

      
    (1) 基本语法:

    有两种判断方法:

    • test 条件判断
    • [ 条件判断 ]   (注意 条件判断 前后都要有空格

    PS:进行条件判断后,想看结果是真还是假,就要用 $? 接受返回值,即输入 echo $? 命令打印返回值结果。条件为真是0,条件为假是1 。

      

    (2) 常用判断条件:

    1. 两个整数之间比较
    符号含义
    -eq等于(equal)
    -ne不等于(not equal)
    -lt小于(less than)
    -gt大于(greater than)
    -le小于等于(less equal)
    -ge大于等于(greater equal)

    注:如果是字符串之间的比较,用等号 = 判断相等;用 != 判断不等。

    1. 按照文件权限进行判断
    符号含义
    -r有读的权限(read)
    -w有写的权限(write)
    -x有执行的权限(execute)

    1. 按照文件类型进行判断
    符号含义
    -e文件存在(existence)
    -f文件存在并且是一个常规的文件(file)
    -d文件存在并且是一个目录(directory)

      
    (3) 多条件判断:

    • && :逻辑与。表示前一条命令执行成功时,才执行后一条命令。
    • || :逻辑或。表示上一条命令执行失败后,才执行下一条命令。

    两者结合可实现三元运算符。

      
    (4) 练习:

    [root@hadoop100 ~]# a=hello
    [root@hadoop100 ~]# test $a = hello
    [root@hadoop100 ~]# echo $?
    0
    [root@hadoop100 ~]# test $a = Hello
    [root@hadoop100 ~]# echo $?
    1

    [root@hadoop100 ~]# [ 2 -lt 8 ]
    [root@hadoop100 ~]# echo $?
    0
    [root@hadoop100 ~]# [ 2 -gt 8 ]
    [root@hadoop100 ~]# echo $?
    1

    [root@hadoop100 ~]# cd scripts/
    [root@hadoop100 scripts]# ls
    add.sh cmd_test.sh fun_test.sh if_elif_else_test2.sh if_test.sh parameter.sh while_test.sh
    case_test.sh for_test.sh hello.sh if_elif_else_test.sh parameter_for_test.sh read_test.sh
    [root@hadoop100 scripts]# [ -x hello.sh ]
    [root@hadoop100 scripts]# echo $?
    0

    [root@hadoop100 scripts]# [ -e hello.sh ]
    [root@hadoop100 scripts]# echo $?
    0

    [root@hadoop100 scripts]# a=15
    [root@hadoop100 scripts]# [ $a -lt 20 ] && echo “a比较小” || echo “a比较大”
    a比较小
    [root@hadoop100 scripts]# a=25
    [root@hadoop100 scripts]# [ $a -lt 20 ] && echo “a比较小” || echo “a比较大”
    a比较大

    返回值为真,执行 || 前面的;返回值为假,执行 || 后面的。

      
      
      

      

    流程控制

      

      

    if 判断

      

    (1) 基本语法:
      

    1. 单分支
    if [ 条件判断式 ]
    then
    	程序
    fi
    
    • 1
    • 2
    • 3
    • 4

    或者

    if [ 条件判断式 ];then
        程序
    fi
    
    • 1
    • 2
    • 3

      

    1. 多分支
    if [ 条件判断式 ]
    then
    	程序
    elif [ 条件判断式 ]
    then
    	程序
    else
    	程序
    fi
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

      
    注意事项:

    1. [ 条件判断式 ],中括号和条件判断式之间必须有空格。
    2. if后要有空格

      

    (2) 练习:

    #!/bin/bash
    
    if [ "$1"x = "hello"x ]
    then
            echo hello,world
    fi
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    [root@hadoop100 scripts]# ./if_test.sh hello
    hello,world

    [root@hadoop100 scripts]# echo $a
    25
    [root@hadoop100 scripts]# if [ $a -gt 18 ] && [ $a -lt 35 ]; then echo 青年人; fi
    青年人

      

    #!/bin/bash
    
    if [ $1 -lt 18 ]
    then
            echo "未成年"
    else
            echo "成年了"
    fi
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    [root@hadoop100 scripts]# ./if_test.sh 20
    成年了

      

    #!/bin/bash
    
    if [ $1 = 1 ]
    then
    	echo 输入了个1
    elif [ $1 = 2 ]
    then
    	echo 输入了个2
    else
    	echo 输入的是其他
    fi
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    [root@hadoop100 scripts]# ./if_elif_else_test.sh 2
    输入了个2

      

    #!/bin/bash
    
    # 输入参数表示年龄,判断属于哪个年龄段
    if [ $1 -lt 18 ]
    then
    	echo 未成年人
    elif [ $1 -lt 35 ]
    then 
    	echo 青年人
    elif [ $1 -lt 60 ]
    then 
    	echo 中年人
    else
    	echo 老年人
    fi
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    [root@hadoop100 scripts]# ./if_elif_else_test2.sh 20
    青年人

      

      

      

    case 语句

      

    (1) 基本语法:

    case $变量名 in
    值1)
    	执行程序1
    ;;
    值2)
    	执行程序2
    ;;
    	......
    *)
    	如果变量的值都不是以上的值,则执行此程序
    ;;
    esac
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

      

    注意事项:

    1. case行尾必须为单词 in ,每一个模式匹配必须以右括号 ) 结束。
    2. 双分号 ;; 表示命令序列结束,相当于Java中的break。
    3. 最后的 *) 表示默认模式,相当于Java中的 default 。

      

    (2) 练习:

    #!/bin/bash
    
    case $1 in
    1)
    	echo one
    ;;
    2)
    	echo two
    ;;
    3)	
    	echo three
    ;;
    *)
    	echo number else
    ;;
    esac
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    [root@hadoop100 scripts]# ./case_test.sh 2
    two
    [root@hadoop100 scripts]# ./case_test.sh 8
    number else

      

      

      

    for 循环

      

    (1) 基本语法:

    for (( 初始值;循环控制条件;变量变化))
    do
    	程序
    done
    
    • 1
    • 2
    • 3
    • 4

      

    (2) 练习:

    #!/bin/bash
    
    for (( i=1;i<=$1;i++ ))
    do
    	sum=$[ sum+i ]
    done
    echo $sum
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    [root@hadoop100 scripts]# ./for_test.sh 100
    5050

      

    (3) 基本语法2:

    for 变量 in 值1 值2 值3...
    do
    	程序
    done
    
    • 1
    • 2
    • 3
    • 4

    增强for循环

      

    (4) 练习2:

    [root@hadoop100 scripts]# for i in 哈哈 嘿嘿 呵呵; do echo $i; done
    哈哈
    嘿嘿
    呵呵

    [root@hadoop100 scripts]# for i in {1…100}; do sum=$[sum+i]; done; echo $sum
    5050

    小tips:

    • ;就代表换了一行
    • {1…100} 表示生成序列,1到100的序列,用于增强for遍历

      

      

      

    while 循环

      

    (1) 基本语法:

    while [ 条件判断式 ]
    do
    	程序
    done
    
    • 1
    • 2
    • 3
    • 4

      

    (2) 练习:

    #!/bin/bash
    
    a=1
    while [ $a -le $1 ]
    do
    #	sum=$[ sum+a ]		第一种写法
    #	a=$[ a+1 ]
    	let sum+=a		# 第二种写法
    	let a++
    done
    echo $sum
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    [root@hadoop100 scripts]# ./while_test.sh 100
    5050

      
      
      

      

    read 读取控制台输入

      

      

    (1) 基本语法:

    read (选项) (参数)
    
    • 1


    ① 选项:

      -p:后跟输入时的提示句。

      -t :后跟输入时系统等待的时间(秒),如果不加 -t 则系统会一直等待。

    ② 参数:

      变量:指定某个变量,随后运行时把值输入给它。

      
      

    (2) 练习:

    #!/bin/bash
    
    read -t 10 -p "请输入名字:" name
    echo Welcome,$name
    
    • 1
    • 2
    • 3
    • 4

    如果一直不输入,10秒后,程序会自动结束

    [root@hadoop100 scripts]# ./read_test.sh
    请输入名字:Welcome,

      
    如果及时输入了,则程序会正常执行

    [root@hadoop100 scripts]# ./read_test.sh
    请输入名字:tony
    Welcome,tony

      
      
      

      

    函数

      

      

      

    一、系统函数

      

      

    1、basename

      

    (1) 基本语法:

    basename [string/pathname] [suffix]
    
    • 1

    功能描述:basename 命令会删掉所有的前缀包括最后一个 / 字符,即只保留最后一个 / 之后的字符。

    basename 可以理解为取路径里的文件名称。

      

    选项:

      suffix :指定要去掉的后缀。如果 suffix 被指定了,basename 会被 pathname 或 string 中的 suffix后缀 去掉。

      
      

    (2) 练习:
      

    截取路径:

    [root@hadoop100 scripts]# basename /root/scripts
    scripts


    还能截取普通字符串:

    [root@hadoop100 scripts]# basename hdasgfua/adgdkh/dfajgk/hahaha
    hahaha


    加上 suffix 参数去掉指定后缀:

    [root@hadoop100 scripts]# basename /root/scripts/hello.sh .sh
    hello

    去掉了 .sh 后缀

    如果 suffix 不是后缀,则错了,不会执行此参数:

    [root@hadoop100 scripts]# basename /root/scripts/hello.sh hello
    hello.sh

    不能去掉 hello 留 .sh ,因为 hello 不是后缀。

      

      

    2、dirname

      

    (1) 基本语法:

    direname string/pathname
    
    • 1

    功能描述:对于pathname,从给定的包含绝对路径的文件名中去除文件名(非目录部分),然后返回剩下的路径(目录部分);对于字符串,删掉后缀包括最后一个 / 字符,即只保留最后一个 / 之前的字符。

    dirname 可以理解为取文件路径的绝对路径名称。

      
      

    (2) 练习:
      
    截取路径:

    [root@hadoop100 scripts]# dirname /root/scripts/hello.sh
    /root/scripts


    还能截取普通字符串:

    [root@hadoop100 scripts]# dirname /hello/java/hadoop/world
    /hello/java/hadoop

      

      

      

    二、自定义函数

      

      

    (1) 基本语法:

    function 函数名()
    {
    	程序;
    	return int;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5


    简化版:

    函数名()
    {
    	程序;
    }
    
    • 1
    • 2
    • 3
    • 4

    function、return 返回值都可以选写。

      

    (2) 经验技巧:

    1. 必须在调用函数地方之前,先声明函数,shell 脚本是逐行运行。不会像其他语言一样先编译。

    2. 函数返回值,只能通过 $? 系统变量获得,可以显示加:return 返回,如果不加,将以最后一条命令运行结果,作为返回值。return 后跟数值 n(0-255)

      

    (3) 练习:

    #!/bin/bash
    
    function add(){
    	s=$[$1+$2]
    	echo "两数之和为:"$s
    }
    
    read -p "请输入第一个整数:" a
    read -p "请输入第二个整数:" b
    
    add $a $b
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    [root@hadoop100 scripts]# ./fun_test.sh
    请输入第一个整数:35
    请输入第二个整数:25
    两数之和为:60

      

    改进版:
    函数中最后用 echo 模拟返回函数的返回值。

    #!/bin/bash
    
    function add(){
            s=$[$1+$2]
            echo $s
    }
    
    read -p "请输入第一个整数:" a
    read -p "请输入第二个整数:" b
    
    sum=$(add $a $b)
    echo "两数之和为:"$sum
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

      
      
      

      

    文本处理工具

      

      

      

    cut

      

    cut 的工作就是 “剪”,具体地说就是在文件中负责剪切数据用的。cut 命令从文件的每一行剪切字节、字符和字段,并将这些字节、字符和字段输出。

      
    (1) 基本用法:

    cut [选项参数] filename
    
    • 1

    说明:默认分隔符是制表符 \t

      

    (2) 选项参数说明:

      -f :列号。提取第几列

      -d :分隔符。按照指定分隔符分割列,默认是制表符 \t

      -c :按字符进行切割,后加数字,表示取第几列。比如 -c 2

      

    (3) 练习:

    查看要用的数据

    [root@hadoop100 scripts]# cat cut.txt
    dong shen he
    guan zhen nan
    wo wo wo
    lai lai lai
    le le le

      
    切割 cut.txt 第一列

    [root@hadoop100 scripts]# cut -d " " -f 1 cut.txt
    dong
    guan
    wo
    lai
    le

      
    切割 cut.txt 第二、三列

    [root@hadoop100 scripts]# cut -d " " -f 2,3 cut.txt
    shen he
    zhen nan
     wo
     lai
     le

      
    在 cut.txt 文件中切割出 guan

    这能截取一行

    [root@hadoop100 scripts]# cat cut.txt | grep guan
    guan zhen nan

    这一行中再切第一列

    [root@hadoop100 scripts]# cat cut.txt | grep guan | cut -d " " -f 1
    guan

      

      

    awk

      

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

      
    (1) 基本用法:

    awk [选项参数]  '/pattern1/{action1}  /pattern2/{action2}...'	filename
    
    • 1

      

    pattern:表示 awk 在数据中查找的内容,就是匹配模式

    action :在找到匹配内容时所执行的一系列命令

      

    (2) 选项参数说明:

      -F :指定输入文件的分隔符

      -v :赋值一个用户定义变量

      

    (3) 练习:

    搜索 passwd 文件以 root 关键字开头的所有行,并输出该行的第7列

    [root@hadoop100 scripts]# cat /etc/passwd | grep ^root | cut -d “:” -f 7
    /bin/bash
    [root@hadoop100 scripts]# cat /etc/passwd | awk -F “:” ‘/^root/ {print $7}’
    /bin/bash

      
    搜索 passwd 文件以 root 关键字开头的所有行,并输出该行的第1列和第7列,中间以“,”分割。

    [root@hadoop100 scripts]# cat /etc/passwd | awk -F “:” ‘/^root/ {print $1","$7}’
    root,/bin/bash

  • 相关阅读:
    Linux系统配置静态IP地址步骤
    5种在TypeScript中使用的类型保护
    智能城市环境中的医疗物联网:基于量子同态加密的医疗成像架构(Idea)
    haproxy集成国密ssl功能[下]
    从零开始搭建Electron项目之运行例程
    支付模块实现
    信息系统项目管理师教程 第四版【第2章-信息技术发展-思维导图】
    【react】Hooks原理和实战
    【项目】若依框架如何实现批量导入,并解析出表中内容返回给前端? - poi依赖
    高防服务器是怎样进行防御的?
  • 原文地址:https://blog.csdn.net/qq_56952363/article/details/125510118