Shell编程

目录
1.Shell基础知识
2.判断和循环语句
3.函数与中断、字符串的处理
4.正则表达式、SED文本编辑器
5.AWK数据过滤与数据分析
---------------------------------------


1. Shell基础知识 1)常见shell解释器 /bin/bash /bin/sh /bin/csh /bin/tcsh 2)通过usermod、chsh可以更改登陆Shell 3)标准输入与输出的重定向 > :标准输出,覆盖写入 >>:标准输出,追加写入 2>:错误输出,覆盖写入 2>>:错误输出,追加写入 &>:标准和错误一起纯输出,覆盖写入,和 > txt 2>&1 效果一样 4)source命令执行脚本文件,不会启动子进程,通过pstree查看进程树 5)环境变量 存储在/etc/profile或~/.bash_profile 命令env可以列出所有环境变量 常见环境变量:PATH、PWD、USER、UID、HOME、SHELL 6)位置变量 存储脚本执行时的参数 使用$n表示,n为数字序列号 $1、\(2、...、\){10}、${11}、... eg:通过位置变量创建系统账户,配置密码 useradd "$1"    echo "$2" | passwd --stdin "$1" 7)预定义变量   
8)区分三种定界符
    双引号 " ":允许扩展,以 $ 引用其他变量
    单引号 ' ':禁用扩展,即便 $ 也视为普通字符
    反引号 ` `:将命令的执行输出作为变量值,$()与反引号等效

9)read 从键盘读入变量值完成赋值
    格式: read  [ -p "提示信息" ]  变量名
    -p可选,-t 可指定超时秒数,-s设置是否在终端显示输入的内容
    [root@localhost ~]# vim /root/shell/day01/read.sh 
    #!/bin/bash
    read -p "请输入用户名:"   name
    read -p "请输入密码:" -s  pass
    useradd "$name"
    echo "$pass" | passwd --stdin "$name"
    [root@localhost ~]# bash /root/shell/day01/read.sh 
    请输入用户名:jerry
    请输入密码:

10)变量作用域
==>局部变量
    新定义的变量默认只在当前Shell环境中有效,无法在子Shell环境中使用

==>全局变量
    全局变量在当前Shell及子Shell环境中均有效
    [root@localhost ~]# x=11        #定义局部变量
    [root@localhost ~]# sh                  #进入子Shell
    sh-4.2# echo $x                            #无此变量,输出为空
    sh-4.2# exit                #退出子Shell
    
    [root@localhost ~]# export x=11    #定义全局变量

11)计算
  $[]算式替换
    使用 $[ ] 或 $(( )) 表达式
    格式:$[整数1  运算符  整数2 .. ..]
    计算结果替换表达式本身,可结合echo命令输出
  Bash内建机制仅支持整数运算,不支持小数运算
    [root@localhost ~]# echo $[3.5+2.2]
    -bash: 3.5+2.2: 语法错误: 无效的算术运算符 (错误符号是 ".5+2.2")
    我们可以通过计算器软件bc实现小数运算
    如果没有该软件则需要使用yum安装
    bc支持交互式和非交互式两种方式计算,scale=n可以约束小数位
   bc计算器
    scale=n可以约束小数位
    quit退出交互式计算

12)echo回显
    -n选项:不换行
    -e选项:支持扩展属性
    [root@localhost ~]# echo "hello world"             #换行
    hello world
    [root@localhost ~]# echo -n "hello world"         #不换行
    hello world[root@localhost ~]# 
    [root@localhost ~]# echo -e  "\033[31mOK\033[0m"   #红色显示OK
    [root@localhost ~]# echo -e  "\033[32mOK\033[0m"   #绿色显示OK
    [root@localhost ~]# echo -e  "\033[34mOK\033[0m"   #蓝色显示OK

2.判断和循环语句
1)判断
==>字符串比较
    · 是否为空 [ -z  字符串 ]
    · 等于[ 字符串1 == 字符串2 ]
    · 不等于[ 字符串1 != 字符串2 ]

==>整数值比较
  
==>文件状态
   


==>基础命令: tr -s 删除多余重复的字串 [root@localhost ~]# echo "a b c" | tr -s " " #删除多余的空格 [root@localhost ~]# echo "aaacaaaaaq" | tr -s "a" #删除多余的a ==>cut过滤数据 [root@localhost ~]# cut -d: -f1 /etc/passwd #以冒号为分隔,过滤第一列 2)for循环 for 变量 in 值列表 do 命令序列 done ------------------------------ for ((初值;条件;步长)) do 命令序列 done 3)case语法 case 变量 in 模式1) 命令序列1 ;; 模式2) 命令序列2 ;; .. .. *) 默认命令序列 esac 4)数组 数组也是一个变量,是一个有点特殊的变量 存储多个数据的集合就是数组 [root@localhost ~]# test=(11 22 33) #定义数组 [root@localhost ~]# echo ${test[0]} #调用数组的值 11 [root@localhost ~]# echo ${test[1]} 22 [root@localhost ~]# echo ${test[2]} 33 5)多进程命令 [root@localhost ~]# vim /root/shell/day03/mutiping.sh #!/bin/bash myping() { ping -c3 -i0.2 -W1 $1 &>/dev/null if [ $? -eq 0 ];then echo "$1 is up" else echo "$1 is down" fi } for i in {1..254} do myping "192.168.4.$i" & done wait #使用&符号,将执行的函数放入后台执行,wait等待所有后台进程结束后退出脚本 3.函数与中断、字符串的处理 1)脚本的中断和退出 continue可以结束单次循环 break可以结束循环体 exit可以退出脚本 [root@localhost ~]# for i in {1..5} do [ $i -eq 3 ] && continue echo $i done echo over 2)字符串处理 ==>字符串截取 ${变量:起始位置:长度} [root@localhost ~]# echo ${#phone} #统计变量长度 11 [root@localhost ~]# echo ${phone:0:3} 138 [root@localhost ~]# echo ${phone:3:3} 123 [root@localhost ~]# echo ${phone:4} 2345678 [root@localhost ~]# echo ${phone:4:-2} 23456 ==>字符串替换 替换1个结果 ${变量/旧字串/新字串} 替换全部结果 ${变量//旧字串/新字串} [root@localhost ~]# phone=13812345678 [root@localhost ~]# [root@localhost ~]# echo ${phone/3/X} 1X812345678 [root@localhost ~]# echo ${phone//3/X} 1X812X45678 ==>字符串掐头 从左向右,最短匹配删除 ${变量#关键词} 从左向右,最长匹配删除 ${变量##关键词} 提示:对变量掐头不会改变变量原有的值! [root@localhost ~]# A=`head -1 /etc/passwd` [root@localhost ~]# echo $A root:x:0:0:root:/root:/bin/bash [root@localhost ~]# echo ${A#*:} x:0:0:root:/root:/bin/bash [root@localhost ~]# echo ${A##*:} /bin/bash ==>字符串去尾 从右向左,最短匹配删除 ${变量%关键词} 从右向左,最长匹配删除 ${变量%%关键词} [root@localhost ~]# A=`head -1 /etc/passwd` [root@localhost ~]# echo $A root:x:0:0:root:/root:/bin/bash [root@localhost ~]# echo ${A%:*} root:x:0:0:root:/root [root@localhost ~]# echo ${A%%:*} root 3)变量初始化 变量有值,则返回该变量的值 变量无值,则返回初始值 格式:${变量:-关键词} [root@localhost ~]# X=123 [root@localhost ~]# echo ${X:-xyz} 123 [root@localhost ~]# [root@localhost ~]# echo ${ABC:-xyz} xyz 4)生产随机密码的方法 ==>子串截取生产随机密码 [root@localhost ~]# vim /root/shell/day03/pass.sh #!/bin/bash #定义变量:10个数字+52个字母. #用随机数对62取余数,返回的结果为[0-61]. key="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" pass="" for i in {1..10} do num=$[RANDOM%${#key}] tmp=${key:num:1} pass=${pass}${tmp} done echo $pass ==>使用命令生成随机密码 uuidgen openssl [root@localhost ~]# uuidgen ebf97979-e2c5-4cfe-abdc-d97f84623796 [root@localhost ~]# openssl rand -base64 10 emwHlGEjQDv0qw== ==>使用随机设备文件(/dev/random、/dev/urandom) tr命令可以对数据进行替换、删除等操作 -c:取反、-d:删除 [root@localhost ~]# tr -cd '0-9a-zA-Z' < /dev/urandom | head -c 10 #删除随机数据中不是数字、小写字母、大写字母的数据 #在截取出来的字串中提取前10个字符 4.正则表达式、SED文本编辑器 1)正则表达式 ==>基本正则   
==>扩展正则
    
==>Perl兼容的正则
  

 


 


==>grep用法 用法:grep [选项] 匹配模式 [文件]… 常用选项: -i 忽略大小写 -v 取反匹配 -w 匹配单词 -q 静默匹配,不将结果显示在屏幕 2sed(Stream Editer,流式编辑器) ==>特点 非交互式 逐行处理 可以对文本进行增、删、改、查等操作 ==>语法: sed [选项] '[定位符]指令' 文件名 命令 | sed [选项] '[定位符]指令' ==>定位符: 行号定位 正则定位 ==>常用指令 p(print):打印行 d(delete):删除行 c(replace):替换行 s(substitution):替换关键词 =:打印行号 Print指令 [root@localhost ~]# sed -n '/IPADDR/p' /etc/sysconfig/network-scripts/ifcfg-eth0 #过滤网卡IP地址 [root@localhost ~]# free | sed -n '/Mem/p' #过滤内存信息 [root@localhost ~]# df -h | sed -n '/\/$/p' #过滤磁盘根分区信息(根分区是以/结尾的分区) [root@localhost ~]# sed -n '1p;3p;6p' /etc/passwd #显示第1、3、6行内容 [root@localhost ~]# sed -n '2!p' /etc/hosts #打印第2行以外的所有其他行内容 Delete指令(不使用-i选项,源文件不会被修改) [root@localhost ~]# sed 'd' /etc/hosts #删除/etc/hosts全文,没有定位条件等于匹配所有行 [root@localhost ~]# cat /etc/fstab > /tmp/fstab [root@localhost ~]# sed '1,3d' /tmp/fstab #1到3行都删除 [root@localhost ~]# sed '/dev/!d' /tmp/fstab #不包含dev的行都删除 [root@localhost ~]# sed '/^#/d' /tmp/fstab #删除所有以#符号开头的行 [root@localhost ~]# sed '/^$/d' /tmp/fstab #删除空白行 Replace指令(不使用-i选项,源文件不会被修改) [root@localhost ~]# sed 'c 123456' /tmp/fstab #所有行替换为123456 [root@localhost ~]# file=/etc/sysconfig/network-scripts/ifcfg-eth0 [root@localhost ~]# sed '/IPADDR/c IPADDR=1.1.1.1' $file #替换IP地址 [root@localhost ~]# sed '/127/c 127.0.0.1 localhost' /etc/hosts [root@localhost ~]# sed '4c xxxx' /etc/shells Substitution指令(不使用-i选项,源文件不会被修改) [root@localhost ~]# vim test.txt 2046 2048 2046 2046 1001 2046 2999 1888 2046 2046 2046 2046 [root@localhost ~]# sed 's/2046/XXXX/' test.txt [root@localhost ~]# sed 's/2046/XXXX/g' test.txt [root@localhost ~]# sed 's/2046/XXXX/2' test.txt [root@localhost ~]# sed 's/2046/(&)/g' test.txt [root@localhost ~]# sed '2s/2046/XXXX/g' test.txt [root@localhost ~]# sed '2s/2046//g' test.txt [root@localhost ~]# sed -n '2s/2046/XXXX/p' test.txt Substitution指令(替换符/可以用其他字符) [root@localhost ~]# vim test.txt 2046 2048 2046 2046 1001 2046 2999 1888 2046 2046 2046 2046 [root@localhost ~]# sed 's#2046#XXXX#g' test.txt [root@localhost ~]# sed 's,2046,XXXX,g' test.txt [root@localhost ~]# sed 's!2046!XXXX!g' test.txt [root@localhost ~]# sed 's2\20462XXXX2g' test.txt [root@localhost ~]# sed 's2\20462\20492g' test.txt 正则符号()具有保留的功能 [root@localhost ~]# echo "hello the world" | sed -r 's/^(.)(.*)(.)$/\3\2\1/' dello the worlh =(打印行号) [root@localhost ~]# sed -n '1=' /etc/passwd [root@localhost ~]# sed -n '/root/=' /etc/passwd [root@localhost ~]# sed -n '/bash$/=' /etc/passwd [root@localhost ~]# sed -n '$=' /etc/passwd #统计行数 28 [root@localhost ~]# wc -l /etc/passwd #统计行数 28 /etc/passwd ==>文本块指令 i(insert):插入 a(append):追加 r(read):读取文件|导入文件内容 wwrite):文件另存为|导出文件内容 Insert(插入,行前写入) [root@localhost ~]# vim test.txt 2046 2048 2046 2046 1001 2046 2999 1888 2046 2046 2046 2046 [root@localhost ~]# sed '2i ABC_XYZ' test.txt [root@localhost ~]# sed '3i ABC_XYZ' test.txt [root@localhost ~]# sed '/2046/i ABC\nXYZ' test.txt [root@localhost ~]# sed '/1888/i ABC\nXYZ' test.txt Append(追加,行后写入) [root@localhost ~]# vim test.txt 2046 2048 2046 2046 1001 2046 2999 1888 2046 2046 2046 2046 [root@localhost ~]# sed '2a ABC_XYZ' test.txt [root@localhost ~]# sed '3a ABC_XYZ' test.txt [root@localhost ~]# sed '/2046/a ABC\nXYZ' test.txt [root@localhost ~]# sed '/1888/a ABC\nXYZ' test.txt Read(将其他文件的内容导入) [root@localhost ~]# vim test.txt 2046 2048 2046 2046 1001 2046 2999 1888 2046 2046 2046 2046 [root@localhost ~]# sed '2r /etc/hosts' test.txt [root@localhost ~]# sed 'r /etc/hosts' test.txt [root@localhost ~]# sed '/1888/r /etc/hosts' test.txt Write(将文件内容导出另存到其他文件) [root@localhost ~]# vim test.txt 2046 2048 2046 2046 1001 2046 2999 1888 2046 2046 2046 2046 [root@localhost ~]# sed 'w copy_test.txt' test.txt #将test.txt文件的所有内容另存为一个新文件copy_test.txt [root@localhost ~]# sed '/1888/w 1888.txt' test.txt #将test.txt文件中所有包含1888的行另存为新文件1888.txt [root@localhost ~]# sed '2,3w line.txt' test.txt #将test.txt文件的2到3行另存为新文件line.txt ==>案例 点名器 [root@localhost ~]# vim /root/shell/day04/roll.sh #!/bin/bash #功能描述(Description):随机点名抽奖器.按Ctrl+C结束脚本. name_file="name.txt" line_file=$(sed -n '$=' $name_file) while : do clear tmp=$(sed -n "$[RANDOM%line_file+1]p" $name_file) echo -e "\033[32m 随机点名器(按Ctrl+C停止):\033[0m" echo -e "\033[32m#############################\033[0m" echo -e "\033[32m# #\033[0m" echo -e "\033[30m $tmp \033[0m" echo -e "\033[32m# #\033[0m" echo -e "\033[32m#############################\033[0m" sleep 0.1 done 5.AWK数据过滤与数据分析 1)概述 awk编程语言/数据处理引擎 创造者:Aho、Weinberger、Kernighan 基于模式匹配检查输入文本,逐行处理并输出 通常用在Shell脚本中,获取指定的数据 单独用时,可对文本数据做统计 2)主要用法 格式1:前置命令 | awk [选项] '[条件]{指令}' 格式2:awk [选项] '[条件]{指令}' 文件.. .. 常用选项:-F可以指定分隔符,默认分隔符为(空格或Tab键) awk内置变量 内置变量都有特殊含义,可直接使用   

 


 

3)awk过滤(可单独使用,也可以同时一起使用)
    在所有行前处理,BEGIN{ }
        读入第一行文本之前执行
        一般用来初始化操作    
    逐行处理,{ }
        逐行读入文本执行相应的处理
        是最常见的编辑指令块
    在所有行后处理,END{ }
        处理完最后一行文本之后执行
        一般用来输出处理结果

4)awk流程控制
单分支if判断
    [root@localhost ~]# awk  -F:   '{if($3>=1000){i++}} END{print i}'   /etc/passwd
    [root@localhost ~]# awk -F: '{if($1=="root"){print $1,$3}}' /etc/passwd
    [root@localhost ~]# uptime | awk  '{ if($NF>0.01){print "CPUload:"$NF}}'

双分支if判断
    [root@localhost ~]# awk  -F:  '{ if($3>=1000){i++} else{j++} }  \
    END{print  "普通用户:" i, "系统用户:" j }' /etc/passwd
    [root@localhost ~]# ls -l  /etc | awk  \
    '{ 
    if($1~/^-/) {x++}  else {y++}     \
    }                               \
    END {print "普通文件个数:"x,"目录个数:"y}'

多分支if判断
    [root@localhost ~]# ls -l  /etc | awk  \
    '{ 
    if($1~/^-/) {x++}  else if ($1~/^d/) {y++} else{z++}    \
    }                               \
    END {print "普通文件个数:"x,"目录个数:"y, "其他个数:"z}'

for循环
    [root@localhost ~]# awk 'BEGIN{ for (i=1;i<=5;i++) {print i}}'
    [root@localhost ~]# awk 'BEGIN{ for (i=5;i>=1;i--) {print i}}'
    
5)awk数组
定义数组
    格式:数组名[下标]=元素值
调用数组
    格式:数组名[下标]
遍历数组
    格式:for(变量名  in  数组名) {print 数组名[变量]}

6)TCP连接状态
三次握手
  
四次断开
  
7)ss命令
  

 


 

 

 

posted @ 2021-09-11 23:48  舍得先森  阅读(160)  评论(0)    收藏  举报