Shell脚本编程

  • 一. SHELL入门
    • 1.1 变量
      • 1.1.1 变量名规范
      • 1.1.2 位置变量
      • 1.1.3 环境变量
    • 1.2 管道
    • 1.3 退出状态码
      • 1.3.1 退出状态码描述
      • 1.3.2 改变退出状态码的exit命令
  • 二. 判断与控制
    • 2.1 if-then 语句
    • 2.2 if-then-else 语句
    • 2.3 嵌套if语句
    • 2.4 条件测试-数值比较
    • 2.5 条件测试-字符串比较
    • 2.6 条件测试-文件比较
    • 2.7 符合条件测试
    • 2.8 if-then中使用双括号
    • 2.9 if-then中使用双方括号
    • 2.10 case命令
  • 三. 循环与控制
    • 3.1 for循环
    • 3.2 while循环
    • 3.3 until命令
    • 3.4 break命令
    • 3.5 continue命令
    • 3.6 处理循环的输出
  • 四. 变量的高级用法
    • 4.1 变量替换和测试
    • 4.2 字符串处理
    • 4.3 命令替换
    • 4.4 有类型变量
    • 4.5 bash数学运算
      • 4.5.1 bash数学运算之expr
      • 4.5.2 bash数学运算之bc
  • 五. 函数的高级用法
    • 5.1 函数定义和使用
    • 5.2 向函数传递参数
    • 5.3 函数返回值
    • 5.4 局部变量和全局变量
    • 5.5 函数库
  • 六. 文件查找
    • 6.1 find命令
    • 6.2 find、locate、whereis和which总结及适用场景分析
  • 七. 文件处理三剑客之grep
    • 7.1 grep命令
      • 7.1.1 语法格式
      • 7.1.2 grep参数
      • 7.1.3 grep和egrep
    • 7.2 文件处理三剑客之sed
      • 7.2.1 sed工作模式
      • 7.2.2 sed选项
      • 7.2.3 sed中的pattern详解
      • 7.2.4 sed中的编辑命令详解
      • 7.2.5 反向引用
      • 7.2.6 利用sed查找文件内容
      • 7.2.7 利用sed删除文件内容
      • 7.2.8 利用sed修改文件内容
      • 7.2.9 利用sed追加文件内容
    • 7.3 文本处理三剑客之awk
      • 7.3.1 awk工作模式
      • 7.3.2 awk内置变量
      • 7.3.3 awk格式化输出之printf
      • 7.3.4 awk模式匹配的两种用法
      • 7.3.5 awk表达式用法
      • 7.3.6 awk动作中的条件及循环语句
      • 7.3.7 awk中的字符串函数
      • 7.3.8 awk的常用选项
      • 7.3.9 awk中数组的用法
      • 7.3.10 实例
  • 八. Shell脚本操作数据库实战
    • 8.1 导入测试数据
      • 8.1.1 载入数据
      • 8.1.2 赋予用户数据库权限
    • 8.2 Shell脚本与MySQL数据库交互
      • 8.2.1 mysql命令参数详解:
      • 8.2.2 实例
    • 8.3 利用Shell脚本将文本数据导入到MySQL中
    • 8.4 备份MySQL数据,并通过FTP将其传输到远端主机
      • 8.4.1 mysqldump常用参数详解:
      • 8.4.2 FTP常用指令
      • 8.4.3 需求
  • 九. 大型脚本工具开发实战
    • 9.1 需求描述:
    • 9.2 功能函数代码
    • 9.3 程序主流程设计及代码实现

一. SHELL入门

1.1 变量

1.1.1 变量名规范

  • 变量是由任何字母、数字、下划线组成的字符串,且不能以数字开头。
  • 区分字母大小写
  • 变量、等号、值中间不能出现任何空格

实例

注:$ var1+$ var2并不能实现相加,$ var1,$ var2默认作为字符串来处理

1.1.2 位置变量

当一条命令或脚本执行时,后面可以跟多个参数,我们使用位置参数变量来表示这些参数。

位置参数变量 描述
$n n 为数字,$ 0 代表Shell本身的文件名,$ 1〜$ 9 代表第 1 ~ 9 个参数,10 以上的参数需要用大括号包含, 如 $ {10}
$* 命令行所有参数,把所有的参数看成一个整体
$@ 命令行中所有参数,但每个参数区别对待
$# 命令行中所有参数的个数

实例

$ @和$ *都表示命令行所有参数,但是$ *将命令行的所有参数看成一个整体,而$ @则区分各个参数

1.1.3 环境变量

环境变量是在操作系统中一个具有特定名字的对象,它包含了一个或多个应用程序将使用到的信息。Linux是一个多用户的操作系统,每个用户登录系统时都会有一个专用的运行环境,通常情况下每个用户的默认的环境都是相同的。这个默认环境就是一组环境变量的定义。每个用户都可以通过修改环境变量的方式对自己的运行环境进行配置。

分类

  • 对所有用户生效的环境变量 /etc/profile

  • 对特定用户生效的环境变量 ~ /.bashrc或者~/.bash_profile

  • 临时有效的环境变量 export

常用环境变量

环境变量 含义
PATH 命令搜索的路径
HOME 用户家目录的路径
LOGNAME 用户登录名
PWD 当前所在路径
HISTFILE 历史命令的保存文件
HISTSIZE 历史命令保存的最大行数
HOSTNAME 主机名
SHELL 用户当前使用的SHELL
PS1 一级命令提示符
TMOUT 用户和系统交互过程的超时值
IFS 系统输入分隔符
OFS 系统输出分隔符

实例

1.2 管道

将一个命令的输出作为另一个命令的输入

实例

  • 列出所有安装过的软件包
rpm -qarpm命令是RPM软件包的管理工具
  • 列出与python相关的软件包
rpm -qa | grep pythonLinux grep 命令用于查找文件里符合条件的字符串。-a :将 binary 文件以 text 文件的方式搜寻数据-c :打印匹配次数-f  两个文件相同行  如,grep -f file1 file2-h 不显示匹配行所在文件名-i :忽略大小写的不同,所以大小写视为相同-l 只显示匹配到的文件名-n :顺便输出行号-o 只显示匹配的字符-v :只显示不匹配的行。 --color=auto :可以将找到的关键词部分加上颜色的显示喔!
  • 显示与python相关的软件包的行数
rpm -qa | grep python | wc -lLinux wc命令用于计算字数-c或--bytes或--chars 只显示Bytes数。-l或--lines 只显示行数。-w或--words 只显示字数。--help 在线帮助。--version 显示版本信息。

1.3 退出状态码

1.3.1 退出状态码描述

所有的shell命令都使用退出状态吗来告知shell它已执行完毕

退出状态码是一个0~255的整数值

Linux提供了一个$?来捕获退出状态码的值,所以,可以通过echo语句测试命令是否运行成功。

一般来讲,退出状态 0 表示正常执行,没有遭遇任何问题。其他非零的状态码均表示失败。

状态码 描述
0 命令成功结束
1 一般性未知错误
2 不适合的shell 命令
126 找到了该命令但无法执行
127 没找到命令
128 无效的退出参数
128+x 与linux信号x相关的严重错误
130 通过ctrl+C终止的命令
255 正常范围之外的退出状态码

实例

1.3.2 改变退出状态码的exit命令

退出状态码是以上一条指令的返回结果为准
使用exit命令改变退出状态码

exit $exit_codeexit 48 或者 exit 125 或者exit 0

二. 判断与控制

2.1 if-then 语句

语法:

if command | condition
then commands
fi

实例

#!/bin/bashif pwd
then echo "It works"
fi

2.2 if-then-else 语句

语法:

if command | condition
then commands
elsecommands
fi

实例

#!/bin/bashif pwd
then echo "It works"
fi

2.3 嵌套if语句

语法:

if command | condition
then commands
elif command | condition
thencommands
elsecommands
fi

2.4 条件测试-数值比较

语法:

if condition
then commands
fi或者if condition;then commands
fi

数值比较

数值比较 含义
n1 -eq n2 n1和n2相等,则返回true;否则返回false
n1 -ne n2 n1和n2不相等,则返回true;否则返回false
n1 -gt n2 n1大于n2,则返回true;否则返回false
n1 -ge n2 n1大于等于n2,则返回true;否则返回false
n1 -lt n2 n1小于n2,则返回true;否则返回false
n1 -le n2 n1小于等于n2,则返回true;否则返回false

实例

#!/bin/bashif [ $1 -eq $2 ];then echo "$1 = $2"
elif [ $1 -gt $2 ];then echo "$1 > $2"
elif [ $1 -lt $2 ];then echo "$1 < $2"
fi

2.5 条件测试-字符串比较

字符串比较

字符串比较 含义
str1 = str2 相等比较
str1 != str2 不相等比较
str1 < str2 str1小于str2为true
str1 > str2 str1大于str2为true
-n str1 str1长度不是0则为true
-z str1 str1长度是0则为true

实例

#!/bin/bash
var1='hello'
var2='world'
if [ $var1 = $var2 ];then echo "equal"
elseecho "not equal"
fi

#!/bin/bash
var1='hello'
var2='world'
if [ $var1 < $var2 ];then echo "<"
elseecho ">"
fi

<被当作了重定向,需要进行转义

#!/bin/bash
var1='hello'var2='world'
if [ $var1 \< $var2 ];then echo "<"
elseecho ">"
fi

#!/bin/bash
var1=''
var2='world'
if [ -n "$var1" ];then echo "var1 is not null"
elseecho "var1 is null"
fi

2.6 条件测试-文件比较

文件比较

文件比较 含义
-d file file是否为目录
-f file file是否为文件
-e file file是否存在
-r file file是否可读
-w file file是否可写
-x file file是否可执行
-s file file存在且非空
file1 -nt file2 file1比file2新为true
file1 -ot file2 file1比file2旧为true

实例

#!/bin/bashif [ -d /usr/local ];then echo "yes"
elseecho "no"
fi

#!/bin/bashif [ /usr/local/test1  -nt /usr/local/test2 ];then echo "new"
elseecho "old"
fi

2.7 符合条件测试

语法:

语法1 “与”
if condition1 && condition2
then commands
fi语法2 “或”if condition1 || condition2
then commands
fi

实例

#!/bin/bashvar1=56
var2=34
var3=89
if [ $var1 -gt $var2 ] && [ $var2 -lt $var3 ];then echo " $var1 > $var2 并且  $var2 < $var3"
fi

2.8 if-then中使用双括号

使用双括号进行算术运算

语法:

if ((expression))
then commands
fi

注:

  • 双括号结构中,变量名引用可以加$,也可以不加

  • 运算符前后可以有空格,也可以没有

  • 可以用于if,for,while等循环控制结构中

  • 多个运算符使用逗号分隔

可用运算符

运算符 含义
value++ 后增
value– 后减
++value 先增
–value 先减
! 逻辑求反
== 相等
> 大于
< 小于
>= 大于等于
<= 小于等于
&& 逻辑与

实例

#!/bin/bash
a=10
((a+=10))
echo $a

2.9 if-then中使用双方括号

单方括号语法

if [ $n1 -gt $n2 ] && [ $n2 -lt $n3 ]
then commands
fi改为双方括号语法if [ [$n1 -gt $n2  &&  $n2 -lt $n3 ]]
then commands
fi
注:双括号结构中,变量名引用必须加$[[后面必须要空格,]]前面必须有空格

2.10 case命令

语法:

case $var inpattern1)commands;;pattern2)commands;;;
esac

实例:

#!/bin/bash
case $1 injack)echo "hello,jack";;mike)echo "hello,mike";;*)echo "hello everyone";;
esac

三. 循环与控制

3.1 for循环

循环遍历一系列特定值,然后在结构体中针对每个特定值做处理

语法:

for var in list
do commands
done

实例:

for循环读取列表值:

#!/bin/bash
for i in Beijing Shanghai Nanjing Guangzhou Zhengzhou
do echo "Province is $i"
donefor i in {1..20}
do echo "Number is $i"
done

for循环读取变量值:

#!/bin/bash
list="Zhangsan Lisi Mike Tom"
for i in $list
do echo "Name is $i"
done

#!/bin/bashIFS=$":" #分隔符,默认为空格或tablist="Zhangsan:Lisi:Mike:Tom"
for i in $list
do echo "Name is $i"
done

for循环从命令执行结果读取值

#!/bin/bashFILE=$(ls /opt/)for i in $FILE
do echo "file is $i"
done

#!/bin/bashfor i in $(ls /opt/)
do if [ -d /opt/$i ]thenecho "$i is DIR"elif [ -f /opt/$i ]thenecho "$i is FILE"fi
done

C语言风格的for循环

#!/bin/bashfor ((i=10;i<20;i++))
do echo "Next Number is $i"
done

#!/bin/bash
sum=0
for (( i=1;i<101;i++))
do (( sum+=$i ))
done
echo "sum is $sum"

3.2 while循环

语法:

while command
do commands
done

实例:

#!/bin/bash
num=10
while [ $num -lt 20 ]
do echo "number is $num"((num++))
done

3.3 until命令

语法:

until command
do commands
done

实例:

#!/bin/bash
num=10
until [ $num -eq 0 ]
do echo "number is $num"((num--))
done

3.4 break命令

实例:

#!/bin/bash
num=10
for ((i=1;i<=10;i++))
doif ((i==5))thenbreakelseecho "number is $i"fi
done

当有两层循环的时候,"break 1"跳出内循环; " break 2"跳出外循环

#!/bin/bash
num=10
for ((i=1;i<=10;i++))
dofor((j=1;j<=5;j++))doif ((j==3))thenbreak 1elseecho "$i $j"fidone
done

#!/bin/bash
num=10
for ((i=1;i<=10;i++))
dofor((j=1;j<=5;j++))doif ((j==3))thenbreak 2elseecho "$i $j"fidone
done

3.5 continue命令

实例:

#!/bin/bash
num=10
for ((i=1;i<=30;i++))
doif ((i>15 && i<25))thencontinueelseecho "Number is $i"fi
done

3.6 处理循环的输出

实例

#!/bin/bash
num=10
for ((i=1;i<=100;i++))
doecho "Number is $i"done > result.txt

#!/bin/bash
num=10
for ((i=1;i<=100;i++))
doecho "Number is $i"done | grep "5"

四. 变量的高级用法

4.1 变量替换和测试

变量替换

语法 含义
${变量名#匹配规则} 从变量开头进行规则匹配,将符合最短的数据删除
${变量名##匹配规则} 从变量开头进行规则匹配,将符合最长的数据删除
${变量名%匹配规则} 从变量尾部进行规则匹配,将符合最短的数据删除
${变量名%%匹配规则} 从变量尾部进行规则匹配,将符合最长的数据删除
${变量名/旧字符串/新字符串} 变量内容符合旧字符串规则,则第一个旧字符串会被新字符串取代
${变量名//旧字符串/新字符串} 变量内容符合旧字符串规则,则全部的旧字符串会被新字符串取代

实例

变量测试

实例

4.2 字符串处理

计算字符串长度

方法一:
${#string}方法二:
expr length "$string"  #string如果有空格,则必须加双引号

获取子串在字符串中的索引位置

语法

expr index $string $substring

$substring会被切割成字符,比如orl被切割成o,r,l,分别查找字符,哪个字符最先找到就会返回那个字符的位置,l最靠前,位置为3,返回3

计算子串长度

expr match $string substr


$string会从头开始匹配子串,不能从中间匹配

抽取子串

方法一:
${string:position}                       #从string中的position开始方法二:
${string:position:length}                 #从position开始,匹配长度为length方法三:
${string:-(position)}                       #从右边开始匹配方法四:
${string:(position)}                      #从左边开始匹配方法五:
expr substr $string $position $length     #从position开始,匹配长度为length


练习

需求描述:
变量string=“Bigdata process framework is Hadoop,Hadoop is an open source project” 执行脚本后,打印输出string字符串变量,并给出用户以下选项:

  • 打印string长度
  • 删除字符串中所有的Hadoop
  • 替换第一个Hadoop为Mapreduce
  • 替换全部Hadoop为Mapreduce

用户输入数字1|2|3|4,可以执行对应项的功能;输入qlQ则退出交互模式

脚本:

read命令用于从标准输入中读取输入单行-a:将分裂后的字段依次存储到指定的数组中,存储的起始位置从数组的index=0开始。-d:指定读取行的结束符号。默认结束符号为换行符。-n:限制读取N个字符就自动结束读取,如果没有读满N个字符就按下回车或遇到换行符,则也会结束读取。-N:严格要求读满N个字符才自动结束读取,即使中途按下了回车或遇到了换行符也不结束。其中换行符或回车算一个字符。-p:给出提示符。默认不支持"\n"换行,要换行需要特殊处理,见下文示例。例如,"-p 请输入密码:"-r:禁止反斜线的转义功能。这意味着"\"会变成文本的一部分。-s:静默模式。输入的内容不会回显在屏幕上。-t:给出超时时间,在达到超时时间时,read退出并返回错误。也就是说不会读取任何内容,即使已经输入了一部分。-u:从给定文件描述符(fd=N)中读取数据。
#!/usr/bin/env bashstring="Bigdata process framework is Hadoop,Hadoop is an open source project"function tips_info
{echo "******************************************"echo "***  (1) 打印string长度"echo "***  (2) 在整个字符串中删除Hadoop"echo "***  (3) 替换第一个Hadoop为Mapreduce"echo "***  (4) 替换全部Hadoop为Mapreduce"echo "******************************************"
}function print_len
{if [ -z "$string" ];thenecho "Error,string is null"exit 1elseecho "${#string}"fi
}function del_hadoop
{if [ -z "$string" ];thenecho "Error,string is null"exit 1elseecho "${string//Hadoop/}"fi
}function rep_hadoop_mapreduce_first
{if [ -z "$string" ];thenecho "Error,string is null"exit 1elseecho "${string/Hadoop/Mapreduce}"fi
}function rep_hadoop_mapreduce_all
{if [ -z "$string" ];thenecho "Error,string is null"exit 1elseecho "${string//Hadoop/Mapreduce}"fi
}while true
doecho "【string=\"$string\"】"
tips_info
read -p "Pls input your choice(1|2|3|4|q|Q):" choice
case "$choice" in1)echoecho "Length Of String is: `print_len`"echocontinue;;2)echoecho "删除Hadoop后的字符串为:`del_hadoop`"echo;;3)echo echo "替换第一个Hadoop的字符串为:`rep_hadoop_mapreduce_first`"echo;;4)echo echo "替换第一个Hadoop的字符串为:`rep_hadoop_mapreduce_all`"echo;;q|Q)exit 0;;*)echo "error,unlegal input,legal input only in { 1|2|3|4|q|Q }"continue   ;;
esac
done

4.3 命令替换

语法格式

方法一
`command`方法二
$(command)$(())两个括号用来进行,包括加减乘除数据运算,引用变量前面可以加$,也可以不加$

案例

获取系统的所有用户并输出

cut 命令从文件的每一行剪切字节、字符和字段并将这些字节、字符和字段写至标准输出。如果不指定 File 参数,cut 命令将读取标准输入。必须指定 -b、-c 或 -f 标志之一。参数:-b :以字节为单位进行分割。这些字节位置将忽略多字节字符边界,除非也指定了 -n 标志。-c :以字符为单位进行分割。-d :自定义分隔符,默认为制表符。-f :与-d一起使用,指定显示哪个区域。-n :取消分割多字节字符。仅和 -b 标志一起使用。如果字符的最后一个字节落在由 -b 标志的 List 参数指示的范围之内,该字符将被写出;否则,该字符将被排除
#!/bin/bash
index=1for user in `cat /etc/passwd | cut -d ":" -f 1`
doecho "This is $index user: $user"index=$(($index + 1))
done

根据系统时间计算今年或明年

Linux date命令可以用来显示或设定系统的日期与时间时间方面:% : 印出 %%n : 下一行%t : 跳格%H : 小时(00..23)%I : 小时(01..12)%k : 小时(0..23)%l : 小时(1..12)%M : 分钟(00..59)%p : 显示本地 AM 或 PM%r : 直接显示时间 (12 小时制,格式为 hh:mm:ss [AP]M)%s : 从 1970 年 1 月 1 日 00:00:00 UTC 到目前为止的秒数%S :(00..61)%T : 直接显示时间 (24 小时制)%X : 相当于 %H:%M:%S%Z : 显示时区日期方面:%a : 星期几 (Sun..Sat)%A : 星期几 (Sunday..Saturday)%b : 月份 (Jan..Dec)%B : 月份 (January..December)%c : 直接显示日期与时间%d :(01..31)%D : 直接显示日期 (mm/dd/yy)%h : 同 %b%j : 一年中的第几天 (001..366)%m : 月份 (01..12)%U : 一年中的第几周 (00..53) (以 Sunday 为一周的第一天的情形)%w : 一周中的第几天 (0..6)%W : 一年中的第几周 (00..53) (以 Monday 为一周的第一天的情形)%x : 直接显示日期 (mm/dd/yy)%y : 年份的最后两位数字 (00.99)%Y : 完整年份 (0000..9999)参数说明:-d datestr : 显示 datestr 中所设定的时间 (非系统时间)--help : 显示辅助讯息-s datestr : 将系统时间设为 datestr 中所设定的时间-u : 显示目前的格林威治时间--version : 显示版本编号

根据系统时间获取今年还剩下多少星期,已经过了多少星期

判定nginx进程是否存在,若不存在则自动拉起该进程

#!/bin/bashnginx_process_num=$(ps -ef | grep nginx | grep -v grep | wc -l)if [ $nginx_process_num -eq 0 ];thensystemctl start nginx
fi

4.4 有类型变量

declare和typeset命令

  • declare命令和typeset命令两者等价
  • declare、typeset命令都是用来定义变量类型的

declare命令参数表

参数 含义
-r 将变量设为只读
-i 将变量设为整数
-a 将变量定义为数组
-f 显示此脚本前定义过的所有函数及内容
-F 仅显示此脚本前定义过的函数名
-x 将变量声明为环境变量

输出数组内容:
echo $array[@]}   输出全部内容
echo ${array[1]}  输出下标索引为1的内容获取数组长度:
echo ${#array}    数组内元素个数
echo ${#array[2]} 数组内下标索引为2的元素长度给数组某个下标赋值:
array[0]="lily"    给数组下标索引为1的元素赋值为lily
array[20]="hanmeimei"  在数组尾部添加一个新元素删除元素:
unset array[2] 清除元素
unset array    清空整个数组分片访问:
${array[@]:1:4} 显示数组下标索引从1开始到3的3个元素,不显内容替换:
${array[@]/an/AN}将数组中所有元素内包含an的子串替换为AN数组遍历:
for v in ${array[@]}
do echo $v
done

4.5 bash数学运算

4.5.1 bash数学运算之expr

语法格式
方法一   expr $numl operator $num2
方法二   $(($num1 operator $num2))

expr操作符对照表

操作符 含义
num1|num2 num1不为空且非0,返回num1;否则返回num2
num1&num2 num1不为空且非0,返回num1;否则返回0
num1<num2 num1小于num2,返回1;否则返回0
num1<=num2 num1小于等于num2,返回1;否则返回0
num1=num2 num1等于num2,返回1;否则返回0
num1!=num2 num1不等于num2,返回1;否则返回0
num1>num2 num1大于num2,返回1;否则返回0
num1>=num2 num1大于等于num2,返回1;否则返回0
num1+num2 求和
num1-num2 求差
num1*hum2 求积
num1/num2 求商
num1%num2 求余
在使用的时候需要进行转义
expr $numl \| $num2
expr $numl \& $num2
expr $numl \< $num2
expr $num1 \< $num2r
expr $numl \<=$num2
expr $num1 \>$num2
expr $numl \>=$num2

练习例子

提示用户输入一个正整数num,然后计算1+2+3+…+num的值;必须对num是否为正整数做判断,不符合应当再次允许输入

    #!/bin/bash#while truedoread -p "pls input a positive number: " numexpr $num + 1 &> /dev/nullif [ $? -eq 0 ];thenif [ `expr $num \> 0` -eq 1 ];thenfor((i=1;i<=$num;i++))dosum=`expr $sum + $i`done   echo "1+2+3+....+$num = $sum"exitfifiecho "error,input enlegal"continuedone

4.5.2 bash数学运算之bc

bc介绍

  • bc是bash内建的运算器,支持浮点数运算
  • 内建变量scale可以设置,默认为0

bc操作符对照表

操作符 含义
num1+num2 求和
num1-num2 求差
num1*num2 求积
num1/num2 求商
num1%num2 求余
num1^num2 指数运算

五. 函数的高级用法

5.1 函数定义和使用

函数介绍

  • Linux Shell中的函数和大多数编程语言中的函数一样
  • 将相似的任务或代码封装到函数中,供其他地方调用

语法格式

第一种格式
name()
{command1command2......commandn
}第二种格式
function name
{command1command2......commandn
}

如何调用函数

 - 直接使用函数名调用,可以将其想象成Shell中的一条命令- 函数内部可以直接使用参数$1$2...$n- 调用函数:function name $1 $2

实例

需求描述:写一个监控nginx的脚本;如果Nginx服务宕掉,则该脚本可以检测到并将进程启动,如果正常运行,则不做任何处理

#!/bin/bashthis_pid=$$while true
do
ps -ef | grep nginx | grep -v grep | grep -v $this_pid &> /dev/nullif [ $? -eq 0 ];thenecho "Nginx is running well"sleep 3
elsesystemctl start nginxecho "Nginx is down,Start it...."
fi
done

5.2 向函数传递参数

function name
{echo "Hello $1"echo "Hello $2"
}函数调用:
name Lily Allen

实例
需求描述:
写一个脚本,该脚本可以实现计算器的功能,可以进行+ - * / 四种计算。

#!/bin/bash     function calcu{case $2 in+)echo "`expr $1 + $3`";;-)echo "`expr $1 - $3`";;\\*)echo "`expr $1 \* $3`";;/)echo "`expr $1 / $3`";;esac}calcu $1 $2 $3

5.3 函数返回值

返回值的方式

方法一:  return方法二:    echo

使用return返回值

  • 使用return返回值,只能返回1-255的整数
  • 函数使用return返回值,通常只是用来供其他地方调用获取状态,因此通常仅返回0或1;0表示成功,1表示失败

实例

#!/bin/bash
this_pid=$$function is_nginx_running{ps -ef | grep nginx | grep -v grep | grep -v $this_pid &> /dev/nullif [ $? -eq 0 ];thenreturnelsereturn 1fi}is_nginx_running && echo "Nginx is running" || echo "Nginx is stoped"


使用echo返回值

  • 使用echo可以返回任何字符串结果
  • 通常用于返回数据,比如一个字符串值或者列表值
cut 命令从文件的每一行剪切字节、字符和字段并将这些字节、字符和字段写至标准输出。-b :以字节为单位进行分割。这些字节位置将忽略多字节字符边界,除非也指定了 -n 标志。-c :以字符为单位进行分割。-d :自定义分隔符,默认为制表符。-f :与-d一起使用,指定显示哪个区域。-n :取消分割多字节字符。仅和 -b 标志一起使用。如果字符的最后一个字节落在由 -b 标志的 List 参数指示的范围之内,该字符将被写出;否则,该字符将被排除
#!/bin/bash
function get_users
{users=`cat /etc/passwd | cut -d: -f1`echo $users}user_list=`get_users`index=1for u in $user_listdoecho "The $index user is : $u"index=$(($index+1))done

5.4 局部变量和全局变量

全局变量

  • 不做特殊声明,Shell中变量都是全局变量
  • Tips:大型脚本程序中函数中慎用全局变量

局部变量

  • 定义变量时,使用local关键字
  • 函数内和外若存在同名变量,则函数内部变量覆盖外部变量
#!/bin/bash
var1="Hello world"function test{var2=87}echo $var1
echo $var2testecho $var1
echo $var2

#!/bin/bash
var1="Hello world"function test{local var2=87}testecho $var1
echo $var2

5.5 函数库

为什么要定义函数库

  • 经常使用的重复代码封装成函数文件
  • 一般不直接执行,而是由其他脚本调用

实例
定义一个函数库,该函数库实现以下几个函数
1、加法函数 add
2、减法函数 reduce
3、乘法函数 multiple
4、除法函数 divide
5、打印系统运行情况的函数sys_load,该函数可以显示内存情况


base_function
function add
{echo "`expr $1 + $2`"
}function reduce
{echo "`expr $1 - $2`"
}function multiple
{echo "`expr $1 \* $2`"
}function divide
{echo "`expr $1 / $2`"
}function sys_load
{echo "Memory Info"echofree -mechoecho "Disk Usage"echodf -hecho
}test1.sh#! /bin/bash
. /root/base_functionadd 12 23reduce 90 30multiple 12 12divide 12 2sys_load


总结

  • 库文件的后缀是任意的,但一般使用.lib
  • 库文件通常没有可执行选项
  • 库文件无需和脚本在同级目录,只需在脚本中引用时指定
  • 第一行一般使用#!/bin/echo,输出警告信息,避免用户执行

六. 文件查找

6.1 find命令

语法格式

find [路径] [选项] [操作]

选项参数对照表

选项 含义
-name 根据文件名查找
-perm 根据文件权限查找
-prune 通常和-path一起使用,用于将特定目录排除在搜索条件之外 该选项可以排除某些查找目录
-user 根据文件属主查找
-group 根据文件属组查找
-mtime 根据文件更改时间查找
-nogroup 查找无有效属组的文件
-nouser 查找无有效属主的文件
-newer file1 !file2 查找更改时间比file1新但比file2旧IDE文件
-type 按文件类型查找
-size 按文件大小查找
-mindepth n 从n级子目录开始搜索
-maxdepth n 最多搜索到n级子目录
-exec 对搜索到的文件执行特定的操作,格式为-exec command {} \;

注:
1、{} 和 \ 之间有空格
2、\ 和 ; 之间没有空格!

实例

-typef 文件 find . -type fd 目录 find . -type dc 字符设备文件 find . -type cb 块设备文件 find . -type bl 链接文件 find . -type lp 管道文件 find .-type p 目录下以conf结尾的文件
find /etc -name '*conf'   #-name不区分大小写查找当前目录下文件名为aa的文件,不区分大小写
find . -iname aa查找文件属主为hdfs的所有文件
find . -user hdfs查找文件属组为yarn的所有文件
find . -group yarn查找/etc目录下小于10000字节的文件
find /etc -size -10000c查找/etc目录下大于1M的文件
find /etc -size +1M-mtime -n n天以内修改的文件 +n n天以外修改的文件n 正好n天修改的文件查找/etc目录下5天之内修改且以conf结尾的文件
find /etc -mtime -5 -name1 '*.conf'查找/etc目录下10天之前修改且属主为root的文件
find /etc -mtime +10 -user root查找/etc目录下30分钟之前修改的文件
find /etc -mmin +30查找/etc目录下30分钟之内修改的目录
find /etc -mmin -30 -type d在/etc下的3级子目录开始搜索
find /etc -mindepth 3在/etc下搜索符合条件的文件,但最多搜索到2级子目录
find  /etc   -maxdepth 2 -type f -name '*.conf'查找没有属主的用户
find . -type f -nouser查找没有属组的用户
find .-type f -nogroup-perm例子:
find.-perm 664查找当前目录下所有普通文件,但排除test目录
find . -path ./etc -prune -o -type f查找当前目录下所有普通文件,但排除etc和opt目录
find . -path . /etc -prune -o -path ./opt -prune -o -type f查找当前目录下所有普通文件,但排除etc和opt目录,但属主为hdfs
find . -path ./etc -prune -o -path ./opt -prune -o -type f -a -user hdfs查找当前目录下所有普通文件,但排除etc和opt目录,但属主为hdfs,且文件大小必须大于500字节
find . -path ./etc -prune -o -path ./opt -prune -o -type f -a -user hdfs -a -size +500c搜索/etc下的文件(非目录),文件名以conf结尾,且大于10k,然后将其删除
find . /etc/ -type f -name '*.conf' -size +10k -exec rm -f {} \;将/var/1og/目录下以1og结尾的文件,且更改时间在7天以上的删除
find /var/log/ -name '*.log' -mtime +7 -exec rm -rf{} \;搜索/etc下的文件(非目录),文件名以conf结尾,且大于10k,将其复制到/root/conf目录下
find . /etc/ -size +10k -type f -name '*.conf' -exec cp {} /root/conf/ \;-ok 和exec功能一样,只是每次操作都会给用户提示逻辑运算符:
-a      与
-o      或
-not | !  非查找当前目录下,属主不是hdfs的所有文件
find . -not -user hdfs | find . ! -user hdfs查找当前目录下,属主属于hdfs,且大小大于300字节的文件
find . -type f -a -user hdfs -a -size +300c查找当前目录下的属主为hdfs或者以xm1结尾的普通文件
find . -type f -a \( -user hdfs -o -name '*.xml' \)

6.2 find、locate、whereis和which总结及适用场景分析

locate命令

  • 文件查找命令,所属软件包mlocate

  • 不同于find命令是在整块磁盘中搜索,locate命令在数据库文件中查找

  • find是默认全部匹配,locate则是默认部分匹配

updatedb命令

  • 用户更新/var/lib/mlocate/mlocate.db

  • 所使用配置文件/etc/updatedb.conf

  • 该命令在后台cron计划任务中定期执行

whereis命令

选项 含义
-b 只返回二进制文件
-m 只返回帮助文档文件
-s 只返回源代码文件

which命令
仅查找二进制程序文件

选项 含义
-b 只返回二进制文件

各命令使用场景推荐

命令 适用场景 优缺点
find 查找某一类文件,比如文件名部分一致 功能强大,速度慢
locate 只能查找单个文件 功能单一,速度快
whereis 查找程序的可执行文件、帮助文档等 不常用
which 只查找程序的可执行文件 常用于查找程序的绝对路径

七. 文件处理三剑客之grep

7.1 grep命令

grep 命令用于查找文件里符合条件的字符串。

7.1.1 语法格式

语法1:
grep [option] [ pattern] [file1, file2..]
语法2:
command | grep [option] [pattern]

7.1.2 grep参数

选项 含义
-v 不显示匹配行信息
-i 搜索时忽略大小写
-n 显示行号
-r 递归搜索
-E 支持扩展正则表达式
-F 不按正则表达式匹配,按照字符串字面意思匹配
-c 只显示匹配行总数
-w 匹配整词
-x 匹配整行
-l 只显示文件名,不显示内容
-s 不显示错误信息

7.1.3 grep和egrep

  • grep默认不支持扩展正则表达式,只支持基础正则表达式
  • 使用grep-E可以支持扩展正则表达式使用
  • egrep可以支持扩展正则表达式,与grep-E等价

7.2 文件处理三剑客之sed

7.2.1 sed工作模式

sed(Stream Editor),流编辑器。对标准输出或文件逐行进行处理

语法格式

语法一:
stdout |sed [option] "pattern command"语法二:
sed [option] "pattern command" file

7.2.2 sed选项

选项 含义
-n 只打印模式匹配行
-e 直接在命令行进行sed编辑,默认选项
-f 编辑动作保存在文件中,指定文件执行
-r 支持扩展正则表达式
-i 直接修改文件内容


edit.sed文件写入:

/python/p

7.2.3 sed中的pattern详解

pattern用法表

匹配模式 含义
10command 匹配到第10行
10,20command 匹配从第10行开始,到第20行结束10,
10,+5command 匹配从第10行开始,到第16行结束
/pattern1/command 匹配到pattern1的行
/pattern1/,/pattern2/command 匹配到pattern1的行开始,到匹配到patern2的行结束
10,/pattern1/command 匹配从第10行开始,到匹配到pettern1的行结束
/pattern1/,10command 匹配到pattern1的行开始,到第10行匹配结束

实例

打印file文件的第17行
sed -n "17p" file打印文件的10到20行
sed -n "10,20p" file打印file文件中从第10行开始,往后面加5行
sed -n "10,+5p" file打印file文件中以root开头的行
sed -n "/^root/p" file打印file文件中第一个匹配到以ftp开头的行,到mail开头的行结束
sed -n "/^ftp/,/^mail/p" file打印file文件中从第4行开始匹配,直到以hdfs开头的行结束
sed -n "4,/^hdfs/p" file打印file文件中匹配root的行,直到第10行结束
sed -n "/root/,10p"file

7.2.4 sed中的编辑命令详解

编辑命令对照表

类别 编辑命令 含义
查询 p 打印
= 只显示行号
增加 a 行后追加
i 行前追加
r 外部文件读入,行后追加
w 匹配行写入外部文件
删除 d 删除
修改 s/old/new 将行内第一个old替换为new
s/old/new/g 将行内全部的old替换为new
s/old/new/2g 将行内从第2个old开始到剩下所有的old替换为new
s/old/new/ig 将行内全部的old替换为new,忽略大小写

实例


7.2.5 反向引用

先看一下例子


&和\1引用模式匹配到的整个串
两者区别在于只能表示匹配到的完整字符串,只能引用整个字符串;而\1可以使用()匹配到的字符

sed中引用变量时注意事项:
(1)、匹配模式中存在变量,则建议使用双引号
(2)、sed中需要引入自定义变量时,如果外面使用单引号,则自定义变量也必须使用单引号

#!/bin/bashold_str=hadoop
new_str=HADOOPsed -i "s/$old_str"/"$new_str/g" abc.txt

7.2.6 利用sed查找文件内容

需求描述:
处理一个类似MySQL配置文件my.cnf的文本,示例如下;编写脚本实现以下功能:输出文件有几个段,并且针对每个段可以统计配置参数总个数

my.cnf

# this is read by the standalone daemon and embedded servers
[client]
port=3306
socket=/tmp/mysql.socket#ThisSegmentForserver
[server]
innodb_buffer_pool_size=91750M
innodb_buffer_pool_instances=8
innodb_buffer_pool_load_at_startup=1
innodb_buffer_pool_dump_at_shutdown=1
innodb_data_file_path=ibdata1:1G:autoextend
innodb_flush_log_at_trx_commit=1
innodb_log_buffer_size=32M
innodb_log_file_size=2G
innodb_log_files_in_group=2
innodb_max_undo_log_size=4G
innodb_undo_directory=undolog
innodb_undo_tablespaces=95#thisisonlyforthemysqldstandalonedaemon
[mysqld]
port=3306
socket=/tmp/mysql.sock
basedir=/usr/local/mysql
datadir=/data/mysql
pid-file=/data/mysql/mysql.pid
user=mysql
bind-address=0.0.0.0
sort_buffer_size=16M
join_buffer_size=16M
thread_cache_size=3000
interactive_timeout=600
wait_timeout=600#ThisSegmentFormysqld_safe
[mysqld_safe]
log-error=/var/log/mariadb/mariadb.log
pid-file=/var/run/mariadb/mariadb.pid
max_connections=1000
open_files_limit=65535
thread_stack=512K
external-locking=FALSE
max_allowed_packet=32M#thisisonlyforembeddedserver
[embedded]
gtid_mode=on
enforce_gtid_consistency=1
log_slave_updates
slave-rows-search-algorithms='INDEX_SCAN,HASH_SCAN'
binlog_format=row
binlog_checksum=1
relay_log_recovery=1
relay-log-purge=1#usethisgroupforoptionsthatolderserversdon'tunderstand
[mysqld-5.5]
key_buffer_size=32M
read_buffer_size=8M
read_rnd_buffer_size=16M
bulk_insert_buffer_size=64M
myisam_sort_buffer_size=128M
myisam_max_sort_file_size=10G
myisam_repair_threads=1
lock_wait_timeout=3600
explicit_defaults_for_timestamp=1
innodb_file_per_table=1

预想输出结果:
1:client 2
2:server 12
3:mysqld 12
4:mysqld_safe 7
5:embedded 8
6:mysqld-5.5 10

脚本

#!/bin/bashFILE_NAME=/root/Desktop/dir2/my.cnffunction get_all_segments
{echo "`sed -n '/\[.*\]/p' $FILE_NAME |sed -e 's/\[//g' -e 's/\]//g'`"
}function count_items_in_segment
{echo "`sed -n '/\['$1'\]/,/\[.*\]/p' $FILE_NAME  | grep -v ^# |grep -v ^$ |grep -v "\[.*\]" |wc -l `"
}num=0
for seg in `get_all_segments`
donum=`expr $num + 1`items_count=`count_items_in_segment $seg`echo "$num:$seg  $items_count"
done

7.2.7 利用sed删除文件内容

删除配置文件中的所有注释行和空行
sed -i '/[:blank:]*#/d;/^$/d' nginx.conf在配置文件中所有不以#开头的行前面添加*符号,注意:以#开头的行不添加
sed -i 's/^[^#]/\*&/g' nginx.conf

7.2.8 利用sed修改文件内容

修改用法总结:

1、1s/old/new/2、5,10s/old/new/3、10,+10s/old/new/4、/pattern1/s/old/new/5、/pattern1/,/pattern2/s/old/new/6、/pattern1/,20s/old/new/7、15,/pattern1/s/old/new/

实例

修改/etc/passwd中第1行中第1个root为ROOT
sed -i '1s/root/ROOT/' passwd修改/etc/passwd中第5行到第10行中所有的/sbin/nologin为/bin/bash
sed -i '5,10s/\/sbin\/nologin/\/bin\/bash/g' passwd修改/etc/passwd中匹配到/sbin/nologin的行,将匹配到行中的login改为大写的LOGIN
sed -i '/\/sbin\/nologin/s/login/LOGIN/g' passwd修改/etc/passwd中从匹配到以root开头的行,到匹配到行中包含mail的所有行。修改内为将这些所有匹配到的行中的bin改为HADOOP
sed -i '/^root/,/mail/s/bin/HADOOP/g' passwd修改/etc/passwd中从匹配到以root开头的行,到第15行中的所有行,修改内容为将这些行中的nologin修改为SPARK
sed -i '/^root/,15s/nologin/SPARK/g' passwd修改/etc/passwd中从第15行开始,到匹配到以yarn开头的所有航,修改内容为将这些行中的bin换位BIN
sed -i '15,/^yarn/s/bin/BIN/g' passwd

7.2.9 利用sed追加文件内容

1、a                  在匹配行后面追加
2、i                 在匹配行前面追加
3、r                 将文件内容追加到匹配行后面
4、w                 将匹配行写入指定文件

实例

1、a  append(1)、passwd文件第10行后面追加"Add Line Behind"
sed -i '10a Add Line Begind' passwd
(2)、passwd文件第10行到第20行,每一行后面都追加"Test Line Behind"
sed -i '10,20a Test Line Behind' passwd
(3)、passwd文件匹配到/bin/bash的行后面追加"Insert Line For /bin/bash Behind"
sed -i '/\/bin\/bash/a Insert Line For /bin/bash Behind' passwd2、i(1)、passwd文件匹配到以yarn开头的行,在匹配行前面追加"Add Line Before"
sed -i '/^yarn/i Add Line Before' passwd
(2)、passwd文件每一行前面都追加"Insert Line Before Every Line"
sed -i 'i Insert Line Before Every Line' passwd3、r(1)、将/etc/fstab文件的内容追加到passwd文件的第20行后面
sed -i '20r /etc/fstab' passwd
(2)、将/etc/inittab文件内容追加到passwd文件匹配/bin/bash行的后面
sed -i '/\/bin\/bash/r /etc/inittab' passwd
(3)、将/etc/vconsole.conf文件内容追加到passwd文件中特定行后面,匹配以ftp开头的行,到第18行的所有行
sed -i '//,18r /etc/vconsole.conf' passwd4、w(1)、将passwd文件匹配到/bin/bash的行追加到/tmp/sed.txt文件中
sed -i '/\/bin\/bash/w /tmp/sed.txt' passwd
(2)、将passwd文件从第10行开始,到匹配到hdfs开头的所有行内容追加到/tmp/sed-1.txt
sed -i '10,/^hdfs/w /tmp/sed-1.txt' passwd

7.3 文本处理三剑客之awk

7.3.1 awk工作模式

awk是一个文本处理工具,通常用于处理数据并生成结果报告

awk 'BEGIN{} pattern{commands}END{}' file_name
standard output | awk 'BEGIN{}pattern{commands}END{}'

语法格式说明

语法格式 解释
BEGIN{} 正式处理数据之前执行
pattern 匹配模式
{commands} 处理命令,可能多行
END{} 处理完所有匹配数据后执行

7.3.2 awk内置变量

内置变量 含义
$0 打印行所有信息
$1~$n 打印行的第1到n个字段的信息
NF Number Field 处理行的字段个数
NR Number Row 处理行的行号,从1开始计数
FNR File Number Row 多文件处理时,每个文件单独记录行号,都是从0康凯斯
FS Field Separator 字段分割符,不指定时默认以空格或tab键分割
RS Row Separator 行分隔符,不指定时以回车分割\n
OFS Output Filed Separator 输出字段分隔符。
ORS Output Row Separator 输出行分隔符
FILENAME 处理文件的文件名
ARGC 命令行参数个数
ARGV 命令行参数数组



7.3.3 awk格式化输出之printf

格式符

格式符 含义
%s 打印字符串
%d 打印10进制数
%f 打印浮点数
%x 打印16进制数
%o 打印8进制数
%e 打印数字的科学计数法格式
%c 打印单个字符的ASCII码
修饰符 含义
- 左对齐
+ 右对齐
# 显示8进制在前面加o,显示16进制在前面加0x




实例

1、以字符串格式打印/etc/passwd中的第7个字段,以":"作为分隔符awk 'BEGIN{FS=":"} {printf "%s\n",$7}' /etc/passwd2、以10进制格式打印/etc/passwd中的第3个字段,以":"作为分隔符awk 'BEGIN{FS=":"} {printf "%d\n",$3}' /etc/passwd3、以浮点数格式打印/etc/passwd中的第3个字段,以":"作为分隔符awk 'BEGIN{FS=":"} {printf "%0.3f\n",$3}' /etc/passwd4、以16进制数格式打印/etc/passwd中的第3个字段,以":"作为分隔符awk 'BEGIN{FS=":"} {printf "%#x\n",$3}' /etc/passwd5、以8进制数格式打印/etc/passwd中的第3个字段,以":"作为分隔符awk 'BEGIN{FS=":"} {printf "%#o\n",$3}' /etc/passwd6、以科学计数法格式打印/etc/passwd中的第3个字段,以":"作为分隔符awk 'BEGIN{FS=":"} {printf "%e\n",$3}' /etc/passwd

7.3.4 awk模式匹配的两种用法

第一种
RegExp  按正则表达式匹配
第二种
关系运算匹配  按关系运算匹配

RegExp

匹配/etc/passwd文件行中含有root字符串的所有行

awk 'BEGIN{FS=":"}/root/{print $0}' /etc/passwd

匹配/etc/passwd文件行中以yarn开头的所有行

awk 'BEGIN{FS=":"}/^yarn/{print $0}' /etc/passwd

运算符匹配

<         小于>          大于<=         小于等于>=           大于等于==          等于!=            不等于~            匹配正则表达式!~           不匹配正则表达式

实例

以:为分隔符,匹配/etc/passwd文件中第3个字段小于50的所有行信息awk 'BEGIN{FS=":"}$3<50{print $0}' /etc/passwd以:为分隔符,匹配/etc/passwd文件中第3个字段大于50的所有行信息awk 'BEGIN{FS=":"}$3>50{print $0}' /etc/passwd
以:为分隔符,匹配/etc/passwd文件中第7个字段为/bin/bash的所有行信息awk 'BEGIN{FS=":"}$7=="/bin/bash"{print $0}' /etc/passwd以:为分隔符,匹配/etc/passwd文件中第7个字段不为/bin/bash的所有行信息awk 'BEGIN{FS=":"}$7!="/bin/bash"{print $0}' /etc/passwd以:为分隔符,匹配/etc/passwd中第3个字段包含3个以上数字的所有行信息awk 'BEGIN{FS=":"}$3~/[0-9]{3,}/{print $0}' /etc/passwd

布尔运算符匹配:

||&&!

实例

以:为分隔符,匹配/etc/passwd文件中包含hdfs或yarn的所有行信息awk 'BEGIN{FS=":"}$1=="hdfs" || $1=="yarn" {print $0}' /etc/passwd以:为分隔符,匹配/etc/passwd文件中第3个字段小于50并且第4个字段大于50的所有行信息awk 'BEGIN{FS=":"}$3<50 && $4>50 {print $0}' /etc/passwd

7.3.5 awk表达式用法

运算符 含义
+
/
%
^或** 乘方
++x 在返回x变量之前,×变量加1
X++ 在返回x变量之后,×变量加1

实例

使用awk计算/etc/services中的空白行数量

awk '/^$/{sum++}END{print sum}' /etc/services

计算学生课程分数平均值,学生课程文件内容如下:
Allen 80 90 96 98
Mike 93 98 92 91
Zhang 78 76 87 92
Jerry 86 89 68 92
Han 85 95 75 90
Li 78 88 98 100

awk '{total=$2+$3+$4+$4;AVG=total/4;printf "%-8s%5d%5d%5d%5d%0.2f\n",$1,$2,$3,$4,$5,AVG}' student.txt

7.3.6 awk动作中的条件及循环语句

条件语句:

if(条件表达式1)动作
else if(条件表达式2)动作
else动作

以:为分隔符,只打印/etc/passwd中第3个字段的数值在50-100范围内的行信息

awk 'BEGIN{FS=":"}{if($3<50){ printf "%-20s%-20s%-5d\n","小于50的UID",$1,$3} else if($3>100) {printf "%-20s%-20s%-5d\n","大 于100的UID",$1,$3} else{ printf "%-20s%-20s%-5d\n","大于50 小于100的UID",$1,$3}}' /etc/passwd


循环语句:

while循环:while(条件表达式)动作do while循环:do动作while(条件表达式)for循环:for(初始化计数器;计数器测试;计数器变更)动作

实例:

计算1+2+3+4+…+100的和,请使用while、do while、for三种循环方式实现

while

BEGIN{while(i<=100) #不需要事先声明{sum+=ii++}print sum
}

for

BEGIN{for(i=0;i<=100;i++) #不需要事先声明{sum+=i}print sum
}

do while

BEGIN{do{sum+=ii++}while(i<=100)print sum
}

7.3.7 awk中的字符串函数

函数名 解释
length(str) 计算长度
index(str1,str2) 返回在str1中查询到的str2的位置
tolower(str) 小写转换
toupper(str) 大写转换
split(str,arr,fs) 分隔字符串,并保存到数组中
match(str,RE) 返回正则表达式匹配到的子串的位置
substr(str,m,n) 截取子串,从m个字符开始,截取n位。n若不指定,则默认截取到字符串尾
sub(RE,RepStr,str) 替换查找到的第一个子串
gsub(RE,RepStr,str) 替换查找到的所有子串

以:为分隔符,返回/etc/passwd中每行中每个字段的长度

root: x:0:0:root:/root:/bin/bash
4:1:1:1:4:5:9

BEGIN{FS=":"}
{i=0while(i<=NF){if(i==NF)printf "%d",length($i)   elseprintf "%d:",length($i)i++}print ""}


搜索字符串"I have a dream"中出现"ea"子串的位置
awk 'BEGIN{str=“I hava a dream”;location=index(str,“ea”);print location}

awk ‘BEGIN{str=“I hava a dream”;location=match(str,“ea”);print location}’

将字符串"Hadoop is a bigdata Framawork"全部转换为小写
awk ‘BEGIN{str=“Hadoop is a bigdata Framework”;print tolower(str)}’

将字符串"Hadoop is a bigdata Framawork"全部转换为大写
awk ‘BEGIN{str=“Hadoop is a bigdata Framework”;print toupper(str)}’

将字符串"Hadoop Kafka Spark Storm HDFS YARN Zookeeper",按照空格为分隔符,分隔每部分保存到数组array中
awk ‘BEGIN{str=“Hadoop Kafka Spark Storm HDFS YARN Zookeeper”;split(str,arr," ");for(a in arr) print arr[a]}’

搜索字符串"Tranction 2345 Start:Select * from master"第一个数字出现的位置
awk ‘BEGIN{str=“Tranction 2345 Start:Select * from master”;location=match(str,/[0-9]/);print location}’

截取字符串"transaction start"的子串,截取条件从第4个字符开始,截取5位

awk ‘BEGIN{str=“transaction start”;print substr(str,4,5)}’

替换字符串"Tranction 243 Start,Event ID:9002"中第一个匹配到的数字串为$符号

awk ‘BEGIN{str=“Tranction 243 Start,Event ID:9002”;count=sub(/[0-9]+/,"$",str);print count,str}’

awk ‘BEGIN{str=“Tranction 243 Start,Event ID:9002”;count=gsub(/[0-9]+/,"$",str);print count,str}’

7.3.8 awk的常用选项

选项 解释
-v 参数传递
-f 指定脚本文件
-F 指定分隔符
-V 查看awk的版本号

7.3.9 awk中数组的用法

shell中数组的用法:

打印元素:
echo ${array[2]}打印元素个数:
echo ${#array[@]}打印元素长度:
echo ${#array[3]}给元素赋值:
array[3]="Li"删除元素:
unset array[2];unset array分片访问:
echo ${array[@]:1:3}元素内容替换:
${array[@]/e/E}只替换第一个e;
$tarray[@]//e/E}替换所有的e数组的遍历:
for a in array
doecho $a
done 


awk中数组的用法

在awk中,使用数组时,不仅可以使用1.2…n作为数组下标,也可以使用字符串作为数组下标

当使用1.2.3…n时,直接使用array[2]访问元素;需要遍历数组时,使用以下形式:

str="Allen Jerry Mike Tracy Jordan Kobe Garnet"
split(str,array," ")
for(i=1;i<length(array);i++)print array[i]


当使用字符串作为数组下标时,需要使用array[str]形式访问元素;遍历数组时,使用以下形式:

array["var1"]="Jin"
array["var2"]="Hao"
array["var3"]="Fang"
for(a in array)print array[a]

7.3.10 实例

  1. 统计主机上所有的TCP连接状态数,按照每个TCP状态分类
netstat -an | grep tcp | awk '{array[$6]++} END{for(a in array) print a,array[a]}'


2. 计算横向数据总和,纵向数据总和
allen 80 90 87 91
mike 78 86 93 96
Kobe 66 92 82 78
Jerry 98 74 66 54
Wang 87 21 100 43

BEGIN{ printf "%-10s%-10s%-10s%-10s%-10s%-10s\n","Name","Yuwen","Math","English","Physical","Total"
}
{total=$2+$3+$4+$5yuwen_sum+=$2math_sum+=$3english_sum+=$4physical_sum+=$5printf "%-10s%-10d%-10d%-10d%-10d%-10d\n",$1,$2,$3,$4,$5,total
}
END{printf "%-10s%-10d%-10d%-10d%-10d\n","total",yuwen_sum,math_sum,english_sum,physical_sum
}

八. Shell脚本操作数据库实战

8.1 导入测试数据

测试数据
school.sql

--建表
--学生表
CREATE TABLE `student`(`s_id` VARCHAR(20),`s_name` VARCHAR(20) NOT NULL DEFAULT '',`s_birth` VARCHAR(20) NOT NULL DEFAULT '',`s_sex` VARCHAR(10) NOT NULL DEFAULT '',PRIMARY KEY(`s_id`)
);
--课程表
CREATE TABLE `course`(`c_id`  VARCHAR(20),`c_name` VARCHAR(20) NOT NULL DEFAULT '',`t_id` VARCHAR(20) NOT NULL,PRIMARY KEY(`c_id`)
);
--教师表
CREATE TABLE `teacher`(`t_id` VARCHAR(20),`t_name` VARCHAR(20) NOT NULL DEFAULT '',PRIMARY KEY(`t_id`)
);
--成绩表
CREATE TABLE `score`(`s_id` VARCHAR(20),`c_id`  VARCHAR(20),`s_score` INT(3),PRIMARY KEY(`s_id`,`c_id`)
);
--插入学生表测试数据
insert into student values('1001' , 'zhaolei' , '1990-1001-1001' , 'male');
insert into student values('1002' , 'lihang' , '1990-12-21' , 'male');
insert into student values('1003' , 'yanwen' , '1990-1005-20' , 'male');
insert into student values('1004' , 'hongfei' , '1990-1008-1006' , 'male');
insert into student values('1005' , 'ligang' , '1991-12-1001' , 'female');
insert into student values('1006' , 'zhousheng' , '1992-1003-1001' , 'female');
insert into student values('1007' , 'wangjun' , '1989-1007-1001' , 'female');
insert into student values('1008' , 'zhoufei' , '1990-1001-20' , 'female');
--课程表测试数据
insert into course values('1001' , 'chinese' , '1002');
insert into course values('1002' , 'math' , '1001');
insert into course values('1003' , 'english' , '1003');--教师表测试数据
insert into teacher values('1001' , 'aidisheng');
insert into teacher values('1002' , 'aiyinsitan');
insert into teacher values('1003' , 'qiansanqiang');--成绩表测试数据
insert into score values('1001' , '1001' , 80);
insert into score values('1001' , '1002' , 90);
insert into score values('1001' , '1003' , 99);
insert into score values('1002' , '1001' , 70);
insert into score values('1002' , '1002' , 60);
insert into score values('1002' , '1003' , 80);
insert into score values('1003' , '1001' , 80);
insert into score values('1003' , '1002' , 80);
insert into score values('1003' , '1003' , 80);
insert into score values('1004' , '1001' , 50);
insert into score values('1004' , '1002' , 30);
insert into score values('1004' , '1003' , 20);
insert into score values('1005' , '1001' , 76);
insert into score values('1005' , '1002' , 87);
insert into score values('1006' , '1001' , 31);
insert into score values('1006' , '1003' , 34);
insert into score values('1007' , '1002' , 89);
insert into score values('1007' , '1003' , 98);

创建数据库

create database school default character set utf8;

8.1.1 载入数据

mysql  -u  用户名 -p  数据库名  <   数据库文件

查看数据库中的表,数据已经载入

8.1.2 赋予用户数据库权限

 赋予任意主机普通数据用户dbuser,查询、插入、更新、删除 数据库中school任意表的权利。
grant all on school.*  to dbuser@'%'   identified by '123456';grant all on school.*  to dbuser@localhost   identified by '123456';grant select on school.*  to dbuser@'%' identified by '123456' ;grant insert,on school.*  to dbuser@'%' identified by '123456' ;grant update on school.*  to dbuser@'%'  identified by '123456';grant  delete on school.*  to dbuser@'%' identified by '123456';

8.2 Shell脚本与MySQL数据库交互

8.2.1 mysql命令参数详解:

-u 用户名
-p 用户密码
-h 服务器IP地址
-D 连接的数据库
-N 不输出列信息
-B 使用tab键代替默认交互分隔符
-e 执行SQL语句

其他选项
-E 垂直输出
-H 以HTML格式输出
-X 以XML格式输出

8.2.2 实例

写一个脚本,该脚本可以接收两个参数,参数为数据库名称和需要执行的SQL语句

#!/bin/bashuser="dbuser"
password="123456"
db_name="$1"
SQL="$2"
mysql -u"$user" -p"$password" -D "$db_name"  -e "$SQL"

8.3 利用Shell脚本将文本数据导入到MySQL中

需求1:处理文本中的数据,将文本中的数据插入Mysql中

文本数据

1010  jerry   1990-1001-1001  male
1011    mike    1990-12-21      female
1012    tracy   1990-1005-20    male
1013    kobe    1990-1008-1006  male
1014    allen   1989-1007-1001  female
1015    curry   1991-12-1001    female
1016    ztom    1992-1003-1001  female

插入前数据:


脚本

#!/bin/bashuser="dbuser"
password="123456"mysql_conn="mysql -u"$user" -p"$password" "cat data.txt | while read id name birth sex
do $mysql_conn -e "insert into school.student values('$id','$name','$birth','$sex')"
done

需求2:

文本数据

2021|hao|1989-12-21|male
2022|zhang|1989-12-21|male
2023|ouyang|11989-12-21|male
2024|li|11989-12-21|female

脚本:

#!/bin/bashuser="dbuser"
password="123456"IFS='|'cat data.txt | while read id name birth sex
do mysql -u"$user" -p"$password" -e "insert into school.student values('$id','$name','$birth','$sex')"
done

8.4 备份MySQL数据,并通过FTP将其传输到远端主机

8.4.1 mysqldump常用参数详解:

mysqldump

参数 含义
-u 用户名
-p 密码
-h 服务器IP地址
-d 等价于–no-data 只导出表结构
-t 等价于–no-create-info 只导出数据,不导出建表语句
-A 等价于–all-databases
-B 等价于–databases 导出一个或多个数据库
mysqldump -udbuser -p123456 school >db.sql

8.4.2 FTP常用指令

open
与FTP服务器建立连接,例子:open 192.168.184.3

user
有权限登录FTP服务器的用户名和密码,例子:user ftp_user redhat

8.4.3 需求

将school中的score表备份,并且将备份数据通过FTp传输到192.168.184.3的/data/backup目录下

#!/bin/bashdb_user="dbuser"
db_password="123456"ftp_user="ftp_user"
ftp_password="redhat"
ftp_host="192.168.184.3"dst_dir="/data/backup"
time_date="`date+%Y%m%d%H%M%S`"
file_name="school_score_${time_date}.sql"function auto_ftp
{ftp -inv << EOFopen $ftp_hostuser $ftp_user $ftp_passwordcd $dst_dirput $1bye
EOF
}mysqldump -u"$db_user" -p"$db_password" -h"$db_host"  school score > ./$file_name && auto_ftp ./$file_name

每隔一分钟执行一次


crontab是用来定期执行程序的命令。 -e : 执行文字编辑器来设定时程表,内定的文字编辑器是 VI,如果你想用别的文字编辑器,则请先设定 VISUAL 环境变数来指定使用那个文字编辑器(比如说 setenv VISUAL joe)
-r : 删除目前的时程表
-l : 列出目前的时程表*    *    *    *    *
-    -    -    -    -
|    |    |    |    |
|    |    |    |    +----- 星期中星期几 (0 - 7) (星期天 为0)
|    |    |    +---------- 月份 (1 - 12)
|    |    +--------------- 一个月中的第几天 (1 - 31)
|    +-------------------- 小时 (0 - 23)
+------------------------- 分钟 (0 - 59)实例每一分钟执行一次 /bin/ls:* * * * * /bin/ls在 12 月内, 每天的早上 6 点到 12 点,每隔 3 个小时 0 分钟执行一次 /usr/bin/backup:0 6-12/3 * 12 * /usr/bin/backup每月每天的午夜 0 点 20 分, 2 点 20 分, 4 点 20 分....执行 echo "haha":20 0-23/2 * * * echo "haha"

crontab -e

*/1  * *  *  *   sh /root/test.sh  &> /dev/null

九. 大型脚本工具开发实战

9.1 需求描述:

1、实现一个脚本工具,该脚本提供类似supervisor功能,可以对进程进行管理;

2、一键查看所有进程运行状态

3、单个或批量启动进程,单个或批量停止进程

4、提供进程分组功能,可以按组查看进行运行状态,可以按组启动或停止该组内所有进程

Supervisor是用Python开发的一套通用的进程管理程序,能将一个普通的命令行进程变为后台daemon,并监控进程状态,异常退出时能自动重启。它是通过fork/exec的方式把这些被管理的进程当作supervisor的子进程来启动,这样只要在supervisor的配置文件中,把要管理的进程的可执行文件的路径写进去即可。也实现当子进程挂掉的时候,父进程可以准确获取子进程挂掉的信息的,可以选择是否自己启动和报警。supervisor还提供了一个功能,可以为supervisord或者每个子进程,设置一个非root的user,这个user就可以管理它对应的进程。

主要功能函数列表:

  • function get_all_process 返回进程名称列表字符串
  • function get_all_group 返回进程组列表字符串
  • function get_process_info
    返回进程详细信息列表字符串,详细信息包括:运行状态、PID、CPU、MEM、启动时间 注:该函数可以接收一个参数,参数为进程名称
  • unction get_all_process_by_group 返回进程组内的所有进程名称列表字符串 例子:DB组–>“mysql
    postgresgql oracle”

9.2 功能函数代码

process.cfg

[GROUP_LIST]
WEB
DB
HADOOP
YARN[WEB]
nginx
httpd[DB]
mysql
postgresql
oracle[HADOOP]
datanode
namenode
journalnode[YARN]
resourcemanager
nodemanager[nginx]
description="Web Server 1"
program_name=tail
parameter=-f /root/lesson/9.1/tmp/web-nginx.conf[httpd]
description="Web Server 2"
program_name=tail
parameter=-f /root/lesson/9.1/tmp/web-httpd.conf[mysql]
description="High Performance DataBase"
program_name=tail
parameter=-f /root/lesson/9.1/tmp/mysql.conf [postgresql]
description="PG Server"
program_name=tail
parameter=-f /root/lesson/9.1/tmp/postgresql.conf[oracle]
description="The Best DB Server In The World"
program_name=tail
parameter=-f /root/lesson/9.1/tmp/oracle.conf[datanode]
description="NODE: Storage Data For HDFS"
program_name=tail
parameter=-f /root/lesson/9.1/tmp/hdfs-datanode.xml[namenode]
description="NODE: Storage MetaData For HDFS"
program_name=tail
parameter=-f /root/lesson/9.1/tmp/hdfs-namenode.xml[journalnode]
description="Data synchronization For NameNode"
program_name=tail
parameter=-f /root/lesson/9.1/tmp/hdfs-journalnode.xml[resourcemanager]
description="Resource allocation, task scheduling"
program_name=tail
parameter=-f /root/lesson/9.1/tmp/yarn-resourcemanager.xml[nodemanager]
description="Compute nodes to perform tasks assigned by RM"
program_name=tail
parameter=-f /root/lesson/9.1/tmp/yarn-nodemanager.xml

function get_all_group

说明:该函数无需输入任何参数;返回配置文件 process.cfg中所有的组信息,例如WEB、DB等

function  get_all_group
{if [ ! -e $HOME_DIR/$CONFIG_FILE ];thenecho "CONFIG_FILE is not exist .. PLease CHeck.."EXIT 1elseG_LIST=$(sed -n '/\[GROUP_LIST\]/,/\[.*\]/p' process.cfg | egrep -v "(^$|\[.*\])")echo "$G_LIST"fi
}

function get_all_process

说明:该函数无需输入任何参数;返回配置文件 process.cfg中所有的进程信息。

function get_all_process
{for g in `get_all_group`do P_LIST=`sed -n "/\[$g\]/,/\[.*\]/p" process.cfg | egrep -v '^$|\[.*\]'`echo $P_LISTdone
}

function get_process_info

  • function get_process_pid_by_name
    说明:该函数接收一个参数,参数为进程名称;返回值是一个PID的列表,可能有一个PID,也可能有多个

  • function get_process_info_by_pid
    说明:该函数接收一个参数,参数为进程PID;返回值是一个进程运行信息的列表,列表包含运行状态、CPU占用率、内存占用率、进程启动时间

function get_process_pid_by_name
{if [ $# -ne 1 ];thenreturn 1else pids=`ps -ef | grep $1 | grep -v grep | grep -v $0| awk '{print $2}'`echo $pidsfi
}function get_process_info_by_pid
{if [ `ps -ef | awk -v pid=$1 '$2==pid{print}' | wc -l` -eq 1 ] ;thenpro_status="RUNNING"elsepro_status="STOPED"fipro_cpu=`ps aux | awk -v pid=$1 '$2==pid{print $3}'`pro_mem=`ps aux | awk -v pid=$1 '$2==pid{print $4}'`pro_start_time=`ps -p $1 -o lstart | grep -v STARTED`
}

function is_group_in_config
说明:该函数接收一个参数,参数为组的名称;返回值是0或1,0代表该组在配置文件中,1代表该组不在配置文件中

function is_group_in_config
{for gn in `get_all_group`;doif [ $gn = $1 ];thenreturnfidoneecho "Group $1 is not in process.cfg"return 1}

function get_all_process_by_group

说明:该函数接收一个参数,参数为组名称;返回值是对应组内的所有进程名称列表

function is_group_in_config
{for gn in `get_all_group`;doif [ $gn = $1 ];thenreturnfidonereturn 1}function get_all_process_by_group
{is_group_in_config $1if [ $? -eq 0 ];thenp_list=`sed -n "/\[$1\]/,/\[.*\]/p" process.cfg | egrep -v "(^$|\[.*\])"`echo $p_listelseecho "GroupName $1 is not in process.cfg"fi}

function get_group_by_process_name

说明:该函数接收一个参数,参数是一个进程名称;返回值是一个组名


function get_group_by_process_name
{for gn in `get_all_group`;dofor pn in `get_all_process_by_group $gn`;doif [ $pn == $1 ];thenecho "$gn"fi done done
}

function format_print

说明:该函数接收二个参数,第一个参数为process_name,第二个参数为组名称返回值,是针对每一个进程PID的运行信息

function format_print
{ps -ef | grep $1 | grep -v grep | grep -v $this_pid &> /dev/nullif [ $? -eq 0 ];thenpids=`get_process_pid_by_name $1`for id in $pids;doget_process_info_by_pid $idawk -v p_name=$1 \-v g_name=$2 \-v p_status=$pro_status \-v p_cpu=$pro_cpu \-v p_mem=$pro_mem \-v p_start_time=$pro_start_time 'BEGIN{printf "%-10s%-10s%-5s%-5s%-5s%-5s%-15s\n",p_name,g_name,p_status,p_cpu,p_mem,p_start_time}'doneelseawk -v p_name=$1  -v g_name=$2 'BEGIN{printf "%-10s%-10s%-5s%-5s%-5s%-5s%-15s\n",p_name,g_name,"NULL","NULL","NULL","NULL","NULL"}'fi    }

function is_process_in_config

说明:该函数接收一个参数,参数为进程名称;返回值是0或1,0代表该进程在配置文件中,1代表进程不在配置文件中

function is_process_in_config
{for pn in `get_all_process`;doif [ $pn = $1 ];thenreturnfidoneecho "Process $1 is not in process.cfg"return 1
}

9.3 程序主流程设计及代码实现

./app_status.sh 执行有三种情况:

  • 无参数 列出配置文件中所有进程的运行信息
  • -g GroupName 列出GroupName组内的所有进程
  • process_name 列出指定进程的运行信息
if [ ! -e $HOME_DIR/$CONFIG_FILE ];thenecho "CONFIG_FILE is not exist .. PLease CHeck.."exit 1
fiawk 'BEGIN{printf "%-16s%-10s%-10s%-10s%-10s%-10s%-20s\n","ProcessName---","GroupNmae---","Status---","Pid----","Cpu-----","Memory---","StartTime---"}'if [ $# -gt 0 ];thenif [ "$1" == "-g" ];thenshiftfor gn in  $@;dois_group_in_config $gn || continuefor pn in `get_all_process_by_group $gn`;dois_process_in_config $pn && format_print $pn $gndonedoneelsefor pn in $@;dogn=`get_group_by_process_name $pn`is_process_in_config $pn && format_print $pn $gndonefielsefor pn in `get_all_process`;dogn=`get_group_by_process_name $pn`is_process_in_config $pn && format_print $pn $gndone
fi

Shell脚本编程-总相关推荐

  1. 如何快速入手 Shell 脚本编程

    Linux Shell 脚本编程之前一直没有系统的去学习,在写 Shell 脚本的时候总需要现查各种语法.本文章以编程语言的维度去系统的学习 Shell 脚本编程. Shell Linux Shell ...

  2. 【Linux命令行与Shell脚本编程】三,Linux文件系统

    Linux命令行与Shell脚本编程 第三章 Linux文件系统 文章目录 Linux命令行与Shell脚本编程 三.Linux文件系统 3.1,查看文件 3.1.1,ls 命令 选项和参数 3.1. ...

  3. shell脚本编程学习笔记1(xdl)——shell基础与Bash基本功能()

    shell脚本编程学习笔记1--shell基础与Bash基本功能 1,简介: 1,Shell就是一个命令行解释器,用以连接输入设别和内核. 2,Shell是解 释执行的脚本语言,在Shell中可以直接 ...

  4. 【Linux】《Linux命令行与shell脚本编程大全 (第4版) 》笔记-汇总 ( Chapter1-Chapter16 )

    一.初识 Linux shell Linux 系统可划分为以下 4 部分. Linux 内核 GNU 工具 图形化桌面环境 应用软件 内核主要负责以下 4 种功能. 系统内存管理 内核通过硬盘上称为交 ...

  5. linux之基础shell脚本编程1 基础变量赋值

    本章主要介绍函数的基础,变量赋值,逻辑运算,条件表达式,测试 linux之基础shell脚本编程1  基础变量赋值 linux之基础shell脚本编程2 if语句循环判断 linux之基础shell脚 ...

  6. Linux shell 脚本编程-实战篇(二)

    继: Linux shell 脚本编程-实战篇(一) 2. 创建与数据库.Web及电子邮件相关的脚本 2.1 MySQL 数据库 2.1.1 MySQL 数据库安装 到 http://repo.mys ...

  7. SHELL脚本编程之文本处理

    SHELL脚本编程之文本处理 文件处理三剑客之grep grep命令 语法格式 grep参数 grep和egrep 文件处理三剑客之sed sed工作模式 sed选项 sed中的pattern详解 s ...

  8. shell脚本编程神器之awk语法案例详解

    AWK入门指南 文章目录 shell脚本编程神器之awk语法案例详解 安装AWK AWK 起步示例 AWK程序的结构 执行 awk 程序 awk 的错误提示 简单输出 打印每一行 打印特定行 NF,字 ...

  9. Shell脚本编程教程

    1.Shell脚本语言的基本结构 1.1 Shell脚本的用途: 自动化常用命令 执行系统管理和故障排除 创建简单的应用程序 处理文本或文件 1.2 Shell脚本基本结构: ​ Shell脚本编程: ...

最新文章

  1. word2016提示mathtype文件未找到:MathPage.wll
  2. websocket中发生数据丢失_tcp协议;websocket协议;同源策略和跨域
  3. java中的boolean_java中boolean的用法
  4. 立镖机器人浙江_立镖在美国获2020 NextGen供应链解决方案奖
  5. 第三十四期:花了一个星期,我终于把RPC框架整明白了!
  6. 如何在 Linux 中快速地通过 HTTP 提供文件访问服务
  7. 贪心+单调栈——去除重复字母(Leetcode 316)
  8. SPRING IN ACTION 第4版笔记-第二章-004-Bean是否单例
  9. php input file 上传文件类型,php轻松实现文件上传功能
  10. 解除极域电子教室软件控屏的方法
  11. 用c++随机生成10小学生算术题的课设
  12. UML各种箭头的含义
  13. Python爬虫教程(一):基础知识
  14. linux修改文档拥有人为,Linux系统修复
  15. C语言实现扫雷小游戏(具体步骤+具体说明)
  16. GPU 编程 CPU 异同点_分析师:英特尔(INTC.US)GPU不会构成威胁
  17. 【Python百日进阶-数据分析】Day325 - plotly.express.scatter_3d():3D散点图
  18. 湖南多校对抗赛(2015.03.28)
  19. java程序编译成exe文件_将java程序编译成独立运行的exe文件
  20. 十七项网页恶意代码,别去害人啊!

热门文章

  1. Android一种实现夜间模式方式,同时解决调用recreate() 时闪屏问题
  2. C语言if语句练习题
  3. nginx反向代理打印日志_nginx反向代理笔记
  4. 自动生成艾宾浩斯记忆规律背单词时间表的Matlab脚本
  5. 相机内存卡恢复软件数据恢复方法
  6. 时间模块,os模块,sys模块
  7. idea switch 没有自动提示 Idea switch 语句设置自动提示 Idea 配置switch语句快捷键 swi idea常用快捷键设置
  8. 页面描述语言采用html,全国2014年4月自学考试网页设计与制作试题
  9. windows中禁止U盘写入
  10. 关于软件研发的一些体会总结