zoukankan      html  css  js  c++  java
  • Linux(8):linux三剑客sed和awk & Shell 编程(1)

    linux 三剑客 之 sed

    # sed 是什么?
    # sed : 字符流编辑器 Stream Editor; sed 擅长 替换、取行等
    
    # sed 的功能与版本:
        处理纯文本文件、日志、配置文件等 
        增加、删除、修改、查询
        sed --version  # 查看 sed 版本
        
    # sed 语法格式:
        sed [选项] [sed指令] [输入文件]
        sed -i.bak 's#oldboy#oldgirl#g' oldboy.txt        # -i --- sed命令的参数 ;sed --- sed命令,一个指令 ;g    --- 小尾巴, 修饰

    sed 命令的执行流程

    模式空间: sed 从文件读取一行文件后存入的缓冲区 (这个缓冲区是在内存中的)

    sed 常用功能:

    1. 查询
    2. 增加
    3. 删除
    4. 替换
    5. 拓展

    1. sed 常用功能之显示 p (print)

    # 创建测试环境:
    cat>person.txt<<EOF
    101,oldboy,CEO
    102,zhangyao,CTO
    103,Alex,COO
    104,yy,CFO
    105,feixue,CIO
    EOF
    
    # cat>...<<EOF...EOF  表示创建文件 ; cat>>...<<EOF...EOF 表示向文件中追加内容
    
    [root@NEO oldboy]# cat person.txt 
    101,oldboy,CEO
    102,zhangyao,CTO
    103,Alex,COO
    104,yy,CFO
    105,feixue,CIO
    [root@NEO oldboy]# 
    
    # 1.1 显示某一行    
    [root@NEO oldboy]# sed -n '3p' person.txt     # -n 表示 取消默认输出; '3p' 表示显示第3行
    103,Alex,COO
        
    # 1.2 显示连续多行文本
    # 显示第2行到第4行的内容,包含第2行和第4行
    [root@NEO oldboy]#  sed -n '2,4p' person.txt     # '2,4p' 表示显示从第2行到第4行
    102,zhangyao,CTO
    103,Alex,COO
    104,yy,CFO
    
    # 1.3 显示包含 oldboy 的行到 包含104的行
    [root@NEO oldboy]# sed -n '/oldboy/p' person.txt     # '/oldboy/p' ---> 表示 包含 oldboy 的行 ;此时 该行命令 相当于 grep 'oldboy',但 grep 不能过滤范围
    101,oldboy,CEO
    [root@NEO oldboy]# sed -n '/oldboy/,/104/p' person.txt         # '/oldboy/,/104/p' ---> 包含 oldboy 的行 到 包含 104 的行
    101,oldboy,CEO
    102,zhangyao,CTO
    103,Alex,COO
    104,yy,CFO
    [root@NEO oldboy]# sed -n '/oldboy/,/^104/p' person.txt     # '/oldboy/,/^104/p' ---> 表示从包含 oldboy 的行到 以104开头的行
    101,oldboy,CEO
    102,zhangyao,CTO
    103,Alex,COO
    104,yy,CFO
    
    
    # 1.4 过滤多个字符串
    # 默认情况下,sed只支持基本正则表达式;sed 的 -r 参数,可以支持 扩展正则表达式 (| 和 ())
    # 显示包含 oldboy 的行 或者 yy 的行
    [root@NEO oldboy]# egrep 'oldboy|yy' person.txt 
    101,oldboy,CEO
    104,yy,CFO
    [root@NEO oldboy]# sed -rn '/oldboy|yy/p' person.txt     # -r '/oldboy|yy/p' ---> 表示 包含 oldboy 或者 yy 的行
    101,oldboy,CEO
    104,yy,CFO
    
    # sed 命令通过正则表达式进行过滤时,相当于 egrep 
    
    
    # 1.5 查询指定多行
    [root@NEO oldboy]# sed -n '1p;3p' person.txt     #  '1p;3p' ---> 第1行 和 第3行; 多行之间用 逗号 分隔
    101,oldboy,CEO
    103,Alex,COO
    [root@NEO oldboy]# sed -n '1p;2,4p;5p' person.txt     # , 和 ; 搭配使用
    101,oldboy,CEO
    102,zhangyao,CTO
    103,Alex,COO
    104,yy,CFO
    105,feixue,CIO
    [root@NEO oldboy]# sed -n '/oldboy/p;3,5p' person.txt 
    101,oldboy,CEO
    103,Alex,COO
    104,yy,CFO
    105,feixue,CIO

    2. sed 常用功能之增加

    # 2.1 单行增加:
    # 在第3行后面增加一行内容
    [root@NEO oldboy]# cat person.txt 
    101,oldboy,CEO
    102,zhangyao,CTO
    103,Alex,COO
    104,yy,CFO
    105,feixue,CIO
    [root@NEO oldboy]# sed '3a 103.5,Lee,UFO' person.txt     # 3a 表示在第3行的后面增加一行内容,3a 后面的空格没有用,也可以不写
    101,oldboy,CEO
    102,zhangyao,CTO
    103,Alex,COO
    103.5,Lee,UFO
    104,yy,CFO
    105,feixue,CIO[root@NEO oldboy]# cat person.txt     # sed '3a ' 命令并没有真正修改文件内容,如果想要真正修改文件内容,可以用 sed 的 -i 参数
    101,oldboy,CEO
    102,zhangyao,CTO
    103,Alex,COO
    104,yy,CFO
    105,feixue,CIO
    [root@NEO oldboy]# sed '3i 103.5,Lee,UFO' person.txt     # 3i 表示在第3行的前面再增加一行内容;同理, 该命令也没有真正修改文件内容,想要真正修改文件内容也是加上 -i 参数
    101,oldboy,CEO
    102,zhangyao,CTO
    103.5,Lee,UFO
    103,Alex,COO
    104,yy,CFO
    105,feixue,CIO
    
    # 增加单选文本:
        a 参数 :追加 append,在指定行后添加一行或多行文本
        i 参数 :插入 insert,在指定行前添加一行或多行文本
    
    # 在最后一行插入:
    [root@NEO oldboy]# sed -n '$p' person.txt     # 在 sed 命令中, $ 表示最后一行
    105,feixue,CIO
    [root@NEO oldboy]# sed  '$a 103.5,Lee,UFO' person.txt     # 在最后一行插入一行内容
    101,oldboy,CEO
    102,zhangyao,CTO
    103,Alex,COO
    104,yy,CFO
    105,feixue,CIO
    103.5,Lee,UFO
    [root@NEO oldboy]# sed  '$a new,new,new
    old,old,old' person.txt     # 在最后一行增加多行内容,用 
     分隔 (这种方法不常用;此命令已被 cat>>...<<EOF...EOF 替代,而且在最后一行的多行追加一般用 cat>> 方法)
    101,oldboy,CEO
    102,zhangyao,CTO
    103,Alex,COO
    104,yy,CFO
    105,feixue,CIO
    new,new,new
    old,old,old

    3. sed 常用功能之删除

    # 去除空行实战:删除最后一行
    [root@NEO oldboy]# cat person.txt 
    101,oldboy,CEO
    102,zhangyao,CTO
    103,Alex,COO
    104,yy,CFO
    105,feixue,CIO
    [root@NEO oldboy]# sed '$d' person.txt     # 删除最后一行
    101,oldboy,CEO
    102,zhangyao,CTO
    103,Alex,COO
    104,yy,CFO
    [root@NEO oldboy]# sed '1,3d' person.txt  # 删除第1行到第3行; d 表示 delete 
    104,yy,CFO
    105,feixue,CIO
        
    # 企业案例:不显示文件中空行
    [root@NEO oldboy]# vim person.txt 
    [root@NEO oldboy]# cat -nA person.txt     # cat 的 -n 参数表示显示 行号, -A 表示 显示结尾的 $
         1    101,oldboy,CEO$
         2    102,zhangyao,CTO$
         3    $
         4    103,Alex,COO$
         5    $
         6    104,yy,CFO$
         7    $
         8    105,feixue,CIO$
    [root@NEO oldboy]# grep -v '^$' person.txt     # grep -v 表示 排除
    101,oldboy,CEO
    102,zhangyao,CTO
    103,Alex,COO
    104,yy,CFO
    105,feixue,CIO
    [root@NEO oldboy]# sed '/^$/d' person.txt     # sed 的 /^$/ 表示空行
    101,oldboy,CEO
    102,zhangyao,CTO
    103,Alex,COO
    104,yy,CFO
    105,feixue,CIO
        
    # 另一种方法: sed 的 ! 表示 取反; 在 p d 这些参数前面加 !
    [root@NEO oldboy]# sed -n '/^$/p' person.txt     # 显示空行
    
    
    
    [root@NEO oldboy]# sed -n '/^$/!p' person.txt     # 排除空行
    101,oldboy,CEO
    102,zhangyao,CTO
    103,Alex,COO
    104,yy,CFO
    105,feixue,CIO
    [root@NEO oldboy]# 
    [root@NEO oldboy]# sed '$!d' person.txt     # '$!d' : 不删除最后一行
    105,feixue,CIO

    4. sed常用功能之替换

    # 文本替换: sed -i 's#neo#NEO#g' oldboy.log      
        # s 单独使用 ---> 将每一行中 第一处匹配的字符串进行替换
        # g (global:全局) ---> 每一行进行全部替换 --> sed 指令 s 的替换标志之一(全局替换)
        # sed 的 -i 参数 ---> 用于修改文件; -i.ori ---> 自动备份;先备份源文件,然后修改文件的内容
        
    [root@NEO oldboy]# cat person.txt 
    101,oldboy,CEO
    102,zhangyao,CTO
    
    103,Alex,COO
    
    104,yy,CFO
    
    105,feixue,CIO
    [root@NEO oldboy]# sed 's#o#AAAA#' person.txt 
    101,AAAAldboy,CEO
    102,zhangyaAAAA,CTO
    
    103,Alex,COO
    
    104,yy,CFO
    
    105,feixue,CIO
    [root@NEO oldboy]# sed 's#o#AAAA#g' person.txt 
    101,AAAAldbAAAAy,CEO
    102,zhangyaAAAA,CTO
    
    103,Alex,COO
    
    104,yy,CFO
    
    105,feixue,CIO

    5. sed变量替换 (重点)

    [root@NEO oldboy]# x=oldboy        # oldboy 赋值给 x
    [root@NEO oldboy]# y=oldgirl    # oldgirl 赋值给 y (中间不要有空格)
    [root@NEO oldboy]# sed 's#$x#$y#g' person.txt   # '' ---> 所见即所得,所以 '' 中的内容没有被解析
    101,oldboy,CEO
    102,zhangyao,CTO
    
    103,Alex,COO
    
    104,yy,CFO
    
    105,feixue,CIO
    [root@NEO oldboy]# sed "s#$x#$y#g" person.txt         # "" 中的特殊符号($ $() `` !)会被解析 ; $x 表示 x变量  
    101,oldgirl,CEO
    102,zhangyao,CTO
    
    103,Alex,COO
    
    104,yy,CFO
    
    105,feixue,CIO
        
        
    # sed 的反向引用 :参考以前的    
        

    linux 三剑客 之 awk  --- 取列、取行、统计

    1. 基本的awk 执行过程:

    取出 passwd 文件的第二行的第一列和第二列

    [root@NEO ~]# head -2 /etc/passwd
    root:x:0:0:root:/root:/bin/bash
    bin:x:1:1:bin:/bin:/sbin/nologin
    [root@NEO ~]# awk -F ":" 'NR==2{print $1,$2}' /etc/passwd
    bin x
    
    # awk 语法格式:
    # awk 参数 '模式{动作}' 文件   --->  awk 参数 '条件(找谁){干啥}' 文件

    2. 模式匹配:模式与动作

    # 通过正则表达式作为模式
    # awk 使用正则表达式作为模式
    
    # 创建环境:
    mkdir -p /server/files/
    cat >>/server/files/reg.txt<<EOF
    Zhang Dandan    41117397   :250:100:175
    Zhang Xiaoyu    390320151  :155:90:201
    Meng  Feixue    80042789   :250:60:50
    Wu    Waiwai    70271111   :250:80:75
    Liu   Bingbing  41117483   :250:100:175
    Wang  Xiaoai    3515064655 :50:95:135
    Zi    Gege      1986787350 :250:168:200
    Li    Youjiu    918391635  :175:75:300
    Lao   Nanhai    918391635  :250:100:175
    EOF
    # 第1表表示姓,第2列表示名字,第3列表示ID,第4列表示捐款金额
    
    [root@NEO server]# cat /server/files/reg.txt 
    Zhang Dandan    41117397   :250:100:175
    Zhang Xiaoyu    390320151  :155:90:201
    Meng  Feixue    80042789   :250:60:50
    Wu    Waiwai    70271111   :250:80:75
    Liu   Bingbing  41117483   :250:100:175
    Wang  Xiaoai    3515064655 :50:95:135
    Zi    Gege      1986787350 :250:168:200
    Li    Youjiu    918391635  :175:75:300
    Lao   Nanhai    918391635  :250:100:175
    [root@NEO server]#
    
    # 2.1 找出包含 111 的行:
    [root@NEO files]# pwd
    /server/files
    [root@NEO files]# awk '/111/' reg.txt 
    Zhang Dandan    41117397   :250:100:175
    Wu    Waiwai    70271111   :250:80:75
    Liu   Bingbing  41117483   :250:100:175
    
    # 其它的正则表达式的用法在 awk 没什么变化,但 ^ 和 $ 在 awk 中不太一样
        ^    表示 某一列中 以什么开头的字符串(以什么开头的列) : $3~/^oldboy/  表示 第3列中 以 oldboy 开头的字符串, ~ 可理解成 包含
        $    表示 某一列中 以什么结尾的字符串(以什么结尾的列) : $3~/oldboy$/ 同理
    
    # 2.2 显示Xiaoyu的姓名和ID号码
    [root@NEO files]# awk '/Xiaoyu/' reg.txt     # 只有模式(因为没有{});'/Xiaoyu/' 表示包含 Xiaoyu 的行,它相当于 '$0~/Xiaoyu/',即 把一整行当作一列, awk 的 $0 表示把一整行的内容放到了 $0 中(把一整行当作一列)
    Zhang Xiaoyu    390320151  :155:90:201
    [root@NEO files]# awk '$0~/Xiaoyu/' reg.txt 
    Zhang Xiaoyu    390320151  :155:90:201
    [root@NEO files]# awk '/Xiaoyu/{print $1,$2,$3}' reg.txt     # /Xiaoyu/ 表示包含 Xiaoyu 的行
    Zhang Xiaoyu 390320151
    [root@NEO files]# awk '$2~/Xiaoyu/{print $1,$2,$3}' reg.txt     # $2~/Xiaoyu/ 表示 第2列(名字那一列)包含 Xiaoyu 的行
    Zhang Xiaoyu 390320151
    
    
    # 2.3 显示所有以41开头的ID号码的人的全名和ID号码
    [root@NEO files]# awk '$3~/^41/{print $1,$2,$3}' reg.txt     # $3~/^41/  ---> 第3列(ID那一列)以 41 开头
    Zhang Dandan 41117397
    Liu Bingbing 41117483
    
    # 2.4 显示所有ID号码最后一位数字是1或5的人的全名
    [root@NEO files]# awk '$3~/[15]$/{print $1,$2}' reg.txt     # $3~/[15]$/ 表示模式( {}外面的就是模式 ), {print $1,$2} 表示动作
    Zhang Xiaoyu
    Wu Waiwai
    Wang Xiaoai
    Li Youjiu
    Lao Nanhai
    
    
    # 2.5 显示Xiaoyu的捐款,每个值都以 $ 开头,如 $520$200$135
    # 4. awk 里面进行替换的方法 --- gsub 函数 : '{gsub(/要找的内容(支持正则)/,"替换成的内容",$列号)}' 
    [root@NEO files]# awk '{gsub(/:/,"$",$4)}' reg.txt   # 没有输出是因为 awk 没有默认输出
    [root@NEO files]# awk '{gsub(/:/,"$",$4);print}' reg.txt     # 再加上 ;print  就会有输出 
    Zhang Dandan 41117397 $250$100$175
    Zhang Xiaoyu 390320151 $155$90$201
    Meng Feixue 80042789 $250$60$50
    Wu Waiwai 70271111 $250$80$75
    Liu Bingbing 41117483 $250$100$175
    Wang Xiaoai 3515064655 $50$95$135
    Zi Gege 1986787350 $250$168$200
    Li Youjiu 918391635 $175$75$300
    Lao Nanhai 918391635 $250$100$175    # 第4列的 : 替换成了 $ 
    
    # gsub(/目标/,"替换为什么",第几列)
    # gsub(/目标/,"替换为什么")  === gsub(/目标/,"替换为什么",$0)  ---> 整行替换
    [root@NEO files]# awk '$2~/Xiaoyu/{gsub(/:/,"$",$4);print}' reg.txt 
    Zhang Xiaoyu 390320151 $155$90$201
    [root@NEO files]# awk '$2~/Xiaoyu/{gsub(/:/,"$",$4);print $4}' reg.txt 
    $155$90$201
    [root@NEO files]#
    
    # gsub() 是awk 的一个函数 

    3. awk 数组 --- 统计与计算

    # 特殊模式: BEGIN 和 END 
        BEGIN{}      ---> BEGIN里面的内容,会在 awk 读取文件内容之前运行
        # 一般用于测试、计算等
        
        END{}      ---> END里面的内容,会在 awk 读取文件的最后一行之后运行 (END很常用)
        # 用来显示最终结果(前面一直在计算,最后END显示结果)
    
    [root@NEO files]# awk 'BEGIN{print "this is beginning"}'    # 只写了个BEGIN ,后面就不用接文件了 
    this is beginning
    [root@NEO files]# awk 'BEGIN{print "this is beginning"} {print NR,$0}' reg.txt     # {print NR,$0}  ---> NR 表示 行号
    this is beginning    # BEGIN的内容 
    1 Zhang Dandan    41117397   :250:100:175
    2 Zhang Xiaoyu    390320151  :155:90:201
    3 Meng  Feixue    80042789   :250:60:50
    4 Wu    Waiwai    70271111   :250:80:75
    5 Liu   Bingbing  41117483   :250:100:175
    6 Wang  Xiaoai    3515064655 :50:95:135
    7 Zi    Gege      1986787350 :250:168:200
    8 Li    Youjiu    918391635  :175:75:300
    9 Lao   Nanhai    918391635  :250:100:175
    
    
    # 统计 /etc/services 文件里面的空行数量
    [root@NEO files]# awk '/^$/{print NR}' /etc/services     # '/^$/{print NR}'
    22
    266
    299
    320
    326
    393
    461
    474
    479
    486
    494
    506
    512
    518
    583
    584
    [root@NEO files]# awk '/^$/{i=i+1;print i}' /etc/services     # i=i+1 表示 把 i+1 的结果赋值给 i ,每个增加1,所以这个公式用来统计;i=i+1 也可以简写成 i++ ; i=i+1 和 print 之间用 ; 分隔
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    [root@NEO files]# 
    
    # i=i+1  === i++  --->  用来统计
    
    [root@NEO files]# awk '/^$/{i=i+1}END{print i}' /etc/services     # {i=i+1}END{print i}  ---> i=i+1 是先计算,END{print i} 表示 文件读取文件最后一行后 执行 {print i}
    16
    [root@NEO files]# awk '/^$/{i++}END{print i}' /etc/services     # i++ 相当于 i=i+1
    16

    awk 数组案例详解与awk总结

    #awk数组-统计与计算
    
    # awk 数组的组成:
        hotel[110]="张三"    
        # hotel 表示 数组的名字(酒店名称), 110 表示数组的元素名称(房间号), 张三 表示 元素内容(房间内容) ; hotel[110] 组成了一个数组
    
    [root@NEO files]# awk 'BEGIN{hotel[110]="NEO";hotel[114]="XO";print hotel[110],hotel[114]}'        # 110]="NEO" ---> 创建数组;print hotel[110]  ---> 把数组中的内容显示出来
    NEO XO
    
    
    # 处理以下文件内容,将域名取出并根据域名进行计数排序处理:(百度和sohu面试题)
    http://www.etiantian.org/index.html
    http://www.etiantian.org/1.html
    http://post.etiantian.org/index.html
    http://mp3.etiantian.org/index.html
    http://www.etiantian.org/3.html
    http://post.etiantian.org/2.html
        
        
        
    [root@NEO files]# cat url.txt 
    http://www.etiantian.org/index.html
    http://www.etiantian.org/1.html
    http://post.etiantian.org/index.html
    http://mp3.etiantian.org/index.html
    http://www.etiantian.org/3.html
    http://post.etiantian.org/2.html
    [root@NEO files]# awk -F "[/.]+" '{print $2}' url.txt     # 让 $2 作为数组的元素
    www
    www
    post
    mp3
    www
    post    
        
    # h[$2]  表示 把 第2列(www post mp3)作为元素名称组成一个数组;一共有 3个元素
    # h[$2]++ 表示 每个元素名称 遇到相同的元素名称时 加1,遇到不同的元素名称时不做处理
    # h["www"] 表示 www 这个元素名称中的 元素内容
        
    [root@NEO files]# awk -F "[/.]+" '{h[$2]=h[$2]+1;print h["www"]}' url.txt 
    1
    2
    2
    2
    3
    3
    [root@NEO files]# 
        
    # 显示所有元素的内容
    [root@NEO files]# awk -F "[/.]+" '{h[$2]++}END{print h["www"],h["post"],h["mp3"]}' url.txt 
    3 2 1
    
    # awk 自己提供的循环,可用于显示数组里面的内容: for(pol in h) ---> h是数组,pol 是h数组中的变量(数组的元素名称;遍历的也是数组的元素)
    [root@NEO files]# awk -F "[/.]+" '{h[$2]++}END{for(pol in h) print pol}' url.txt 
    www
    mp3
    post    # 遍历的是 数组的元素名称
        
    [root@NEO files]# awk -F "[/.]+" '{h[$2]++}END{for(pol in h) print h[pol]}' url.txt     # 把 元素名称 放到 数组h中
    3
    1
    2
    [root@NEO files]# awk -F "[/.]+" '{h[$2]++}END{for(pol in h) print pol,h[pol]}' url.txt 
    www 3
    mp3 1
    post 2

    shell编程基础:

    shell编程所需的基础知识:

    熟练使用 vim 编辑器
    熟练 SSH终端
    熟练掌握 Linux常用命令
    熟练掌握Linux正则表达式及三剑客命令(grep sed awk)

    shell编程基础知识与环境

    基础知识:

    # 1. 什么是Shell ?
    # 命令解释器; 你输入的命令,谁来给你解释/运行
    # CentOS默认的 Shell 是 bash :
        echo $SHELL
        /etc/passwd
        .sh 结尾的文件
        file 命令也可以查看文件类型
        
    [root@NEO ~]# echo $SHELL
    /bin/bash
    [root@NEO ~]# cat /etc/shells 
    /bin/sh
    /bin/bash
    /sbin/nologin
    /bin/dash
    /bin/tcsh
    /bin/csh
    [root@NEO ~]# file /etc/init.d/iptables 
    /etc/init.d/iptables: POSIX shell script text executable  # shell script ---> shell脚本
        
    # 2. 什么是Shell脚本?
        # 命令大礼包 --- 一个程序文件,包含若干行Linux命令语句
        # 循环,条件语句
        
    # 创建shell脚本:
    # 1. 统一脚本存放目录
            # 如: /server/scripts/
            
    # 2. 推荐使用 vim 编辑器编程脚本
            # 因为 vim 自带颜色
    # 3. 第一行指出由哪个解释器来执行脚本中的内容:
            #!/bin/bash ---> #! 称为幻数,能被内核识别
                        ---> 必须写在第一行,如果不是第一行则为脚本注释行
                        ---> 双可以写为  #!/bin/sh
    # 4. 版权声明
    # 5. 写一个简单脚本(切换目录显示文件属性)并运行
    
    
    # 脚本目录示例:
    [root@NEO ~]# 
    [root@NEO ~]# ls -l /server/scripts/
    total 8
    -rw-r--r-- 1 root root 66 Apr  7 23:22 ip.sh
    -rw-r--r-- 1 root root  9 Apr  7 14:30 show_date.sh
    
    
    # 脚本注释 & 版权声明:
    [root@NEO ~]# vim /server/scripts/ip.sh
    [root@NEO ~]# cat /server/scripts/ip.sh 
    #!/bin/bash                        #!/bin/bash 表示 这个脚本是用 /bin/bash 运行解释的
    # desc:           show ip address
    # author:      neo
    # time:        20190416
    # version:     v1.0
    
    /sbin/ifconfig eth0 |awk -F "[ :]+" 'NR==2{print $4}'
    [root@NEO ~]# file /server/scripts/ip.sh 
    /server/scripts/ip.sh: Bourne-Again shell script text executable
    [root@NEO ~]# /server/scripts/ip.sh        # 正常运行脚本的方法:通过绝对路径
    -bash: /server/scripts/ip.sh: Permission denied        # 在linux 中创建的文件默认的权限是 644
    [root@NEO ~]# sh /server/scripts/ip.sh        # 以后在执行脚本的时候都是运行 sh 命令
    10.0.0.200

    变量

    # 3.1 什么是变量?
        # 用一个固定的字符串,替代更多更复杂的内容
        # x=1
        # devPath=/server/
        # filelist=`ls` 或 $(ls)
        # 引用变量: $x 相当于 ${x}
        
    [root@NEO ~]# echo $PATH $LANG        # 环境变量
    /usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin en_US.UTF-8
    [root@NEO ~]# x=1        # 往变量中放值 ; x 是普通变量(局部变量)
    [root@NEO ~]# echo $x    # 取出变量中的值
    1
    [root@NEO ~]# 
    
    # 3.2 变量的分类:
    # 3.2.1 局部变量(普通变量):
        只能在创建它们的Shell函数或Shell脚本中使用
        定义变量:
            变量名=value
            变量名要求:
                字母、数字、下划线组成,必须以字母或下划线开头
                规范的变量名写法定义:见名知意
                驼峰语法:首个单词字母小写,其余单词首字母大写 ---> oldAgeSex=1
            把一个命令作为变量
            普通字符串定义测试
    
    [root@NEO ~]# week=10
    [root@NEO ~]# echo $weekday        # 此时系统认为 weekday 这个整体是个变量
    
    [root@NEO ~]# echo ${week}day    # $week 就相当于 ${week}
    10day
    [root@NEO ~]#
    
    # 3.2.2 全局变量(环境变量):
        大写,在Linux中绝大地方都可以用
        在创建他们的Shell及其派生出来的子Shell中使用
        分类:
            查看全局变量: env ---> 只显示全局变量
            bash内置的环境变量:
                Shell通过环境变量来确定 登陆用户名、命令路径、终端类型、登陆日志等
                LANG PAHT SEHLL UID 等
            自定义环境变量:
                建议所有环境变量名均为大写
                必须用 export 命令定义
                取消变量: unset 
                永久生效
                
    
    [root@NEO ~]# echo $LANG $PATH $PS1
    en_US.UTF-8 /usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin [u@h W]$
    [root@NEO ~]# 
    
    # 全局变量 和 局部变量
    [root@NEO ~]# vim /server/scripts/show_date.sh
    [root@NEO ~]# cat /server/scripts/show_date.sh
    #!/bin/hash
    # desc:
    # author:
    # time:
    # version:
    
    echo $OLDBOY
    [root@NEO ~]# OLDBOY=10        # 此时的 OLDBOY 是一个普通变量,在 /server/scripts/show_date.sh  这个脚本中无法使用
    [root@NEO ~]# echo $OLDBOY 
    10
    [root@NEO ~]# sh /server/scripts/show_date.sh      # 输出为空,因为 OLDBOY 是个局部变量,在 这个脚本中无法使用
    
    [root@NEO ~]# # 让普通变量变成全局问题的方法: export 命令; export 是临时生效;取消全局问题的方法 : unset 命令, unset 不但能取消全局变量,也能取消局部变量
    [root@NEO ~]# export OLDBOY        # 让 OLDBOY 这个普通变量 变成 全局变量
    [root@NEO ~]# sh /server/scripts/show_date.sh  
    10        # 此时 OLDBOY 就能在 该脚本中使用了
    [root@NEO ~]# 
    [root@NEO ~]# env |grep OLDBOY
    OLDBOY=10
    [root@NEO ~]# unset OLDBOY
    [root@NEO ~]# env |grep OLDBOY
    [root@NEO ~]# 
    
    
    # 3.2.3 Shell 编程之环境变量相关的文件和目录:
        全局环境变量配置文件:
            /etc/profile    ---> 修改环境变量的文件
            /etc/bashrc
            /etc/profile.d/   ---> 用户登陆到系统 会运行这个目录下面的脚本 ;脚本要有执行权限
        用户自己的环境变量配置文件:
            ~/.bash_profile
            ~/.bashrc
    
    # 修改 /etc/profile.d/ 下的文件 ---> 用户登陆到系统会自动运行
    [root@NEO ~]# ls /etc/profile.d/
    colorls.csh  cvs.csh  glib2.csh  lang.csh  less.csh  vim.csh  which2.sh
    colorls.sh   cvs.sh   glib2.sh   lang.sh   less.sh   vim.sh
    [root@NEO ~]# vim /etc/profile.d/show.sh
    [root@NEO ~]# cat /etc/profile.d/show.sh
    #!/bin/bash
    # desc: show ip address of eth0
    # author: neo
    # time: 20190417
    # version: v1.0
    
    ip a s eth0
    [root@NEO ~]# ll /etc/profile.d/show.sh
    -rw-r--r-- 1 root root 104 Apr 17 02:00 /etc/profile.d/show.sh
    [root@NEO ~]# chmod +x /etc/profile.d/show.sh
    [root@NEO ~]# ll /etc/profile.d/show.sh
    -rwxr-xr-x 1 root root 104 Apr 17 02:00 /etc/profile.d/show.sh
    
    
    WARNING! The remote SSH server rejected X11 forwarding request.
    Last login: Tue Apr 16 20:48:25 2019 from 10.0.0.1
    2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
        link/ether 00:0c:29:26:b5:57 brd ff:ff:ff:ff:ff:ff
        inet 10.0.0.200/24 brd 10.0.0.255 scope global eth0
        inet6 fe80::20c:29ff:fe26:b557/64 scope link 
           valid_lft forever preferred_lft forever
    [root@NEO ~]# 
    
    # 自己写的跳板机放到 /etc/profile.d/ 下面
    
    
    # 特殊变量:
        # 位置变量:
            $0    (在脚本中)
                获取当前执行的shell脚本的文件名
                如果执行脚本带路径那么就包括脚本路径
                模拟系统脚本使用 $0
                
            $n    n 表示数字;$n 表示 第n个参数
            $#    表示参数的个数
        # 进程状态变量
            $?  ---> 显示上一个命令的执行结果;命令执行正确 ---> 结果为0 , 命令执行错误 ---> 结果非0 ;软件安装后可用 $? 判断是否安装成功
            
    
    # 位置变量:
    # 环境创建:
    [root@NEO scripts]# vim show_args.sh
    [root@NEO scripts]# cat show_args.sh 
    #!/bin/bash
    # desc: 
    # author: neo
    # time: 
    # version:
    
    echo '$0:'$0 '$1:'$1 '$2:'$2 '$3:'$3 '$#:'$#    # '$0:' 需要用单引号,双引号的话就被解析了
    [root@NEO scripts]# sh show_args.sh
    $0:show_args.sh $1: $2: $3: $#:0        # $0 表示脚本的名字; $n 在脚本中表示第n个参数
    [root@NEO scripts]# sh show_args.sh arg1 arg2 arg3 arg4 arg5 arg6    # 脚本后面可以跟参数
    $0:show_args.sh $1:arg1 $2:arg2 $3:arg3 $#:6        # $# 表示参数的个数(脚本中一共有多少个参数)
    
    
    [root@NEO scripts]# ls /root/alex.oldboy.txt
    ls: cannot access /root/alex.oldboy.txt: No such file or directory
    [root@NEO scripts]# echo $?
    2        # 执行错误
    [root@NEO scripts]# ls /root/
    alex.txt  anaconda-ks.cfg  data  echotest.txt  install.log.syslog  oldboy-20171111.log
    [root@NEO scripts]# echo $?
    0        # 执行正确
    [root@NEO scripts]#
    
    
    # 变量赋值方法 --- read
    
    # 如何向变量中放内容?
    [root@NEO scripts]# vim show_args.sh 
    [root@NEO scripts]# cat show_args.sh
    #!/bin/bash
    # desc: 
    # author: neo
    # time: 
    # version:
    
    x=1
    y=2
    echo $x $y
    [root@NEO scripts]# sh show_args.sh 
    1 2
    
    # 如果 x y 是动态的参数,则利用下面的方法
    [root@NEO scripts]# vim show_args.sh
    [root@NEO scripts]# cat show_args.sh
    #!/bin/bash
    # desc: 
    # author: neo
    # time: 
    # version:
    
    x=$1    # 改成 $1 和 $2
    y=$2
    echo $x $y
    [root@NEO scripts]# sh show_args.sh 10 20    # 传参10和20;10传给$1 ,20传给 $2
    10 20
    
    # read 能够从命令行中读取内容放到变量中 (交互式的)
    [root@NEO scripts]# read -p "input x y:" x y
    input x y:10 20
    [root@NEO scripts]# echo $x
    10
    [root@NEO scripts]# echo $y
    20
    [root@NEO scripts]# 
    
    
    [root@NEO scripts]# vim show_args.sh 
    [root@NEO scripts]# cat show_args.sh
    #!/bin/bash
    # desc: 
    # author: neo
    # time: 
    # version:
    
    # x=$1
    # y=$2
    
    read -p "input x y:" x y
    echo $x $y
    [root@NEO scripts]# sh show_args.sh
    input x y:30 40
    30 40
    [root@NEO scripts]# 

    循环条件:

    条件表达式:
        格式:[<测试表达式>] 
            先敲一对 [] ,然后退格输入2个空格 [  ],最后再回退一个空格开始输入,即 [] 两端要各有一个空格,如: [ -f /etc/hosts ]
        判断文件:
            -f  ---> 文件是否存在
            -d  ---> 目录是否存在
            0 存在,1 不存在
        判断整数:
            等于 equal                ---> -eq
            不等于 not equal        ---> -ne
            大于 greater than        ---> -gt
            大于等于 greater euqal    ---> -ge
            小于 less than            ---> -lt
            小于等于 less euqal        ---> -le
        简单案例
    
    # Shell编程之测试表达式 --- 中括号
    # [] 表示判断或测试
    [root@NEO scripts]# [ -f /root/alex.oldboy.txt ]    # 判断 /root/alex.oldboy.txt 这个文件是否存在 
    [root@NEO scripts]# echo $?
    1    # 1 表示 [ -f /root/alex.oldboy.txt ] 查找的文件不存在, 0 表示存在
    [root@NEO scripts]# [ -f /oldboy/oldboy.txt ]
    [root@NEO scripts]# echo $?
    0
    [root@NEO scripts]# [ -d /root ]    # 判断 /root 这个目录是否存在; -d 判断目录是否存在 , -f 判断文件是否存在
    [root@NEO scripts]# echo $?
    0
    
    # 判断整数:
    [root@NEO scripts]# [ 1 -eq 1 ]
    [root@NEO scripts]# echo $?
    0
    
    # 判断整数的简单案例:判断命令行参数个数等于2
    [root@NEO scripts]# sh ./args.sh 
    [root@NEO scripts]# sh ./args.sh a b
    arg number is 2
    [root@NEO scripts]# 
    
    # 如果 /oldboy 目录不存在则创建
    [root@NEO ~]# [ -d /oldboy ] || mkdir -p /oldboy/   # 命令1 || 命令2 --->  || 表示 命令1不成立 则执行 命令2
    
    # 如果 /root/oldboy.txt 存在则提示文件已经存在
    [root@NEO ~]# [ -f /oldboy/oldboy.txt ] && echo file exists
    file exists
    
    
    # Shell编程之 if 判断
    # 单分支条件语句:
        # 语法: if [ 条件 ];then 命令 fi    # [] 中括号两端要有两个空格
        # 案例:输入2个字,比较大小
    # 语法:
    
    
    
    # if 单分支:
    [root@NEO scripts]# vim compare.sh
    [root@NEO scripts]# cat compare.sh
    #!/bin/bash
    # desc: 
    # author: neo
    # time: 20190418
    # version: 1.0
    
    num1=$1
    num2=$2
    if [ $num1 -gt $num2 ];then
        echo $num1 greater than $num2
    fi
    [root@NEO scripts]# sh compare.sh 
    greater than
    [root@NEO scripts]# sh compare.sh 10 20
    [root@NEO scripts]# sh compare.sh 20 10
    20 greater than 10
    [root@NEO scripts]# 
    
    # if 双分支:
    [root@NEO scripts]# cat compare.sh 
    #!/bin/bash
    # desc: 
    # author: neo
    # time: 20190418
    # version: 1.0
    
    num1=$1
    num2=$2
    if [ $num1 -gt $num2 ];then
        echo $num1 greater than $num2
    else
        echo $num1 less equal $num2
    fi
    [root@NEO scripts]# sh ./compare.sh 10 20
    10 less equal 20
    [root@NEO scripts]# sh ./compare.sh 20 10
    20 greater than 10
    [root@NEO scripts]# sh ./compare.sh 20 10 1 3 2 5 7        # 不足之处:后4个参数无用
    20 greater than 10
    [root@NEO scripts]# sh ./compare.sh 20
    ./compare.sh: line 9: [: 20: unary operator expected
    20 less equal
    [root@NEO scripts]# 
    
    # 参数必须是2个
    [root@NEO scripts]# cat compare.sh 
    #!/bin/bash
    # desc: 
    # author: neo
    # time: 20190418
    # version: 1.0
    
    num1=$1
    num2=$2
    
    if [ $# -ne 2 ];then
        echo "Useage:please input 2 numbers:num1 num2"
        exit        # 退出程序
    fi
    
    if [ $num1 -gt $num2 ];then
        echo $num1 greater than $num2
    else
        echo $num1 less equal $num2
    fi
    [root@NEO scripts]# sh compare.sh 10
    Useage:please input 2 numbers:num1 num2
    [root@NEO scripts]# sh compare.sh 10 20 30
    Useage:please input 2 numbers:num1 num2
    [root@NEO scripts]# 
    
    
    # if 多分支:
    [root@NEO scripts]# cat compare.sh
    #!/bin/bash
    # desc: 
    # author: neo
    # time: 20190418
    # version: 1.0
    
    num1=$1
    num2=$2
    
    if [ $# -ne 2 ];then
        echo "Useage:please input 2 numbers:num1 num2"
        exit
    fi
    
    if [ $num1 -gt $num2 ];then
        echo $num1 greater than $num2
    elif [ $num1 -lt $num2 ];then
        echo $num1 less equal $num2
    else
        echo $num1 equal to $num2
    fi
    [root@NEO scripts]# 
    
    # shell 不太擅长小数

    Shell编程之 for 循环

    # for 循环语句:
        # 格式:
            for 变量名字 in 列表
            do
                命令
            done
    
    
    [root@NEO scripts]# for num in 1 2 3 4 5
    > do
    > echo "the $num number is:"$num
    > done 
    the 1 number is:1
    the 2 number is:2
    the 3 number is:3
    the 4 number is:4
    the 5 number is:5
    [root@NEO scripts]# 
    
    
    # 优化linux开机启动项目,只保留 crond,sshd,network,rsyslog,sysstat ,其他的都关闭
    # 思路: chkconfig 服务 off
    
    # 第一步:先排除上面的那几个服务
    [root@NEO scripts]# chkconfig |egrep "crond|sshd|network|rsyslog|sysstat" -v
    # 第二步:取出所有的服务名
    [root@NEO scripts]# chkconfig |egrep "crond|sshd|network|rsyslog|sysstat" -v|awk '{print $1}'
    # for 循环遍历关闭
    [root@NEO scripts]# for service in `chkconfig |egrep "crond|sshd|network|rsyslog|sysstat" -v|awk '{print $1}'`
    > do
    >     echo chkconfig $service off    # echo 为了测试
    > done
  • 相关阅读:
    Deepin Linux下安装安卓应用的各种方式
    win下的终端使用指南
    IDEA自定义TODO
    WSL的ssh-agent问题
    MySQL数据类型
    MySQL常用命令.md
    Period 时间坑
    exp/imp管理
    expdp和impdp管理(逻辑导入导出)
    同义词
  • 原文地址:https://www.cnblogs.com/neozheng/p/10687272.html
Copyright © 2011-2022 走看看