内置函数RANDOM可以随机生成随机数其范围为:0~32767
脚本内第一行:#!/bin/bash
标记该脚本要使用的bash环境,不同系统可能需要使用不同的bash环境
执行脚本
1、脚本有执行(x)权限,切换到脚本所在目录下, chmod +x 脚本名
./脚本名.sh
2、脚本没有执行权限,可以在任何目录位置下执行
sh 脚本名.sh
sh -x 脚本名.sh 显示执行过程
sh -n 脚本名.sh 检测脚本语法错误
3、脚本没有执行权限,可以在任何目录位置下执行
source 脚本名.sh
标准输入:从该设备接收用户输入的数据,描述编号:0
设备文件:/dev/stdin,默认设备:键盘
标准输出:通过该设备向用户输出数据,描述编号:1
设备文件:/dev/stdout,默认设备:显示器
标准错误:通过该设备报告执行出错信息,描述编号:2
设备文件:/dev/stderr,默认设备:显示器
重定向输入:< 从文件中读取数据,不通过键盘输入
重定向输出:> 把控制台要显示的内容输出到文件,覆盖文件内原有内容
>> 把控制台要显示的内容输出到文件,在原有内容后追加
标准错误输出:2> 把控制台要输出的错误信息输出到文件
2>>
混合输出:&> 将标准输出、标准错误的内容保存到同一个文件中
&>>
echo "123.com" > pwd.txt
useradd usera
passwd --stdin usera < pwd.txt
samba里如果要给程序用户设置密码,密码文件中的密码要输入两遍
vim pwd.txt
123.com
123.com
pdbedit -a -u usera < pwd.txt
变量:代表某个不确定的值
变量的类型
自定义变量:由用户自己定义、修改和使用
环境变量:由系统维护,用于设置工作环境
位置变量:通过命令行给脚本程序传递参数
预定义变量:Bash中内置的一类变量,不能直接修改
定义变量:变量名=变量值
使用变量:$变量名
输出变量值:echo $变量名
双引号:值为字符串的时候要加"",里面可以引用变量
a="world"
b="Hello $a"
echo $b 结果为 Hello world
单引号:用法跟双引号类似,里面不能引用变量
a="world"
b='Hello $a'
echo $b 结果为 Hello $a
反撇号(1左边那个~) :命令替换,提取命令执行后的输出结果,不能用于命令嵌套
res=`uname -s`
echo $res 结果为linux
$():用法跟反撇号类似,但可以用于命令嵌套
rpm -qf $(which rpm)
先查找rpm命令文件位置,再查看rpm的命令文件是由哪个软件包安装的
从控制台输入内容给变量赋值
read [-p "提示信息"] 变量名
read -p "请输入数字" NUM
请输入数字 23
echo $NUM 结果 23
等待后面的命令一段时间,超时就自动往后运行
stty -icanon min 0 time 100 (100=10秒)
export 变量=变量值 定义全局变量
数字运算
expr 数字1 运算符 数字2
NUM1=10
NUM2=5
NUM3=$(expr $NUM1 + $NUM2)
let NUM3=NUM1+NUM2
NUM3=$(($NUM1 + $NUM2))
+ -
乘:\*
除:/
取余:% 10%3=1
位置变量:
./test.sh one two three four five six
$1 $2 $3 $4 $5 $6
$0:当前执行的进程/程序名
$#:命令行中位置变量的个数
$?:上一条命令执行后返回的状态,当返回状态值为0时表示执行正常,非0值表示执行异常或出错
$*:所有位置变量
测试命令:test
test 条件表达式
[ 条件表达式 ]:条件表达式前后跟中括号之间有空格
条件表达式:判断语句,结果只有真(0)和假(非0)两种
文件测试
-d:测试是否为目录(Directory)
-e:测试目录或文件是否存在(Exist)
-f:测试是否为文件(File)
-r:测试当前用户是否有权限读取(Read)
-w:测试当前用户是否有权限写入(Write)
-x:测试当前用户是否有权限执行(eXcute)
[ -d /etc ]
echo $? 结果为0
整数比较
-eq:等于(Equal)
-ne:不等于(Not Equal)
-gt:大于(Greater Than)
-lt:小于(Lesser Than)
-le:小于或等于(Lesser or Equal)
-ge:大于或等于(Greater or Equal)
[ 2 -gt 1 ]
echo $? 结果为0
字符串比较
=:字符串内容相同
!=:字符串内容不同,! 号表示相反的意思
-z:字符串内容为空
[ -z 字符串 ] 判断一个字符串是否为空
逻辑测试
格式1:[ 表达式1 ] 操作符 [ 表达式2 ] 前后连接两个条件表达式
格式2:命令1 操作符 命令2 ...
&&:①逻辑运算符,并且
②命令连接符,当前一条命令正确执行才执行后一条命令
-a或&&:逻辑与,“而且”的意思
-o或||:逻辑或,“或者”的意思
!:逻辑否
判断是否存在目录/media/cdrom,如果不存在就创建
[ ! -d /media/cdrom ] && mkdir /media/cdrom
单分支结构
if 条件测试操作
then
命令序列
fi
判断是否存在目录/media/cdrom,如果不存在就创建
if [ ! -d /media/cdrom ]
then
mkdir /media/cdrom
fi
双分支结构
if 条件测试操作
then 命令序列1
else 命令序列2
fi
启动服务,成功或失败输出一个提示语句
systemctl start ****
if [ $? = 0 ] $?表示上一条启动服务的命令是否正确执行
then
echo "服务启动成功"
else
echo "服务启动失败"
fi
多分支结构:在条件1不满足的时候去判断条件2
if 条件测试操作1
then 命令序列1
elif 条件测试操作2
then 命令序列2
else
命令序列3
fi
if 分数为85~100之间
then 判为优秀
elif 分数为70~84之间
then 判为合格
esle
判为不合格
fi
数字运算 expr 变量1 运算符 变量2
a=1
b=2
c=$(expr $a + $b) ==> c=$(($a+$b)) ==> let c=a+b
数组:用一个变量表示一组值
在shell中数组长度(就是数组中值的个数)是不定的
用法:
n=(1 2 3 4)
echo ${n[0]} 结果1
[]里是下标(index),从0开始,
0是第一个,1是第二个,...
num=${#n[@]}:num的值就是数组中值的个数
${数组名[@]}:显示数组中的所有值
循环:用来执行大量重复、有规律的操作
for循环(语法1)
for ((初始化变量①;循环条件②;变量迭代③))
do
命令序列④
done
执行过程①->②->④->③->②->④->③->....
直到②中的条件不满足就结束循环执行done后面的命令
遍历数组(输出数组中的每一个值)
n=(1 2 3 4)
for ((i=0;$i<${#n[@]};i++))
do
echo ${n[$i]}
done
计算从1到100相加的值(1+2+3+4+5+...+100)
sum=0
for ((i=1;$i<=100;i++))
do
sum=$(($sum+$i))
done
echo $sum;
乘法表
for ((i=1;$i<10;i++))
do
for ((j=1;$j<=$i;j++))
do
echo -e "${j}*${i}=$(($j*$i))\t\c"
done
echo ""
done
-e 输出的时候支持转义符
\t 制表位
\c 不换行输出
\n 换行输出
for循环(语法2:for each循环)
for 临时变量 in 变量2
do
命令序列
done
临时变量在每一次循环的时候分别表示变量2中的每一个值
从数据库读取用户名和密码,然后在系统中创建相同用户名和密码的用户
create database guigu;
use guigu;
create table stu (
stu_name varchar(50),
stu_pwd varchar(50)
);
insert into stu values ('aa','aa');
....(多插入几条数据)
#!/bin/bash
mysql -u root -p123.com -e "select stu_name from guigu.stu;" > /root/name.txt
mysql -u root -p123.com -e "select stu_pwd from guigu.stu;" > /root/pwd.txt
i=0
NAME=$(cat /root/name.txt)
PWD=$(cat /root/pwd.txt)
NAME1=()
PWD1=()
for SNAME in $NAME
do
NAME1[$i]=$SNAME
let i++
done
i=0
for SPWD in $PWD
do
PWD1[$i]=$SPWD
let i++
done
for ((i=1;$i<${#NAME1[@]};i++))
do
useradd ${NAME1[$i]} >> /dev/null
echo ${PWD1[$i]} | passwd --stdin ${NAME1[$i]} >> /dev/null
done
while循环
while 循环条件
do
命令序列
done
计算从1到100相加的值(1+2+3+4+5+...+100)
#sum=0
#i=1
#while [ $i -lt 101 ]
#do
# sum=$(($sum+$i))
# let i++
#done
#echo $sum
sum=0
i=0
while [ $i -lt 100 ]
do
let i++
sum=$(($sum+$i))
done
echo $sum
while循环必须要有一个改变条件变量的命令,否则会死循环
case多分支选择结构
case 变量 in
值1)
命令序列1
;;
值2)
命令序列2
;;
...
*)
默认命令序列
esac
变量如果是值1,就执行序列1,如果是值2,就执行序列2,...
如果都不是,就执行默认序列
;;用来打断,只要匹配上某个值,就不会继续往下执行
vim test.sh
#!/bin/bash
case $1 in
start)
echo "启动服务$2"
;;
stop)
echo "停止服务$2"
;;
status)
echo "查看服务$2"
;;
*)
echo "请输入正确指令"
esac
sh test.sh start httpd
结果:启动服务httpd
正则表达式:
是使用单个字符串来描述、匹配一系列符合某个句法规则的字符串
正则表达式组成
普通字符
大小写字母、数字、标点符号及一些其他符号
元字符
在正则表达式中具有特殊意义的专用字符
基础正则表达式的常见元字符
^、用在一个字符串前,表示以..开头(^[a-z],表示小写字母开头的行)
$、用在一个字符串后,表示以..结尾(,$),表示用,结尾的行
.、表示最多一个任意字符
\、转义符,用在一个符号前,取消该符号的特殊作用("\"",用来表示一个")
*、用在一个字符串后,表示这个字符串出现0或多次(a*,表示字母a出现0到多次)
[ ]、表示内容包含的内容([a],表示包含小写字母a,[5]表示包含数字5)
[^]、表示内容不包含的范围([^A-Z],表示不包含大写字母)
[n1-n2]、表示内容包含一个范围([a-z],表示包含小写字母,[0-9]表示包含数字)
{n}、表示前面的字符串出现的次数最多n次,可以不连续
([a-z]{5},表示最多有5个小写字母)
{n,}、表示前面的字符串出现的次数至少n次,可以不连续
([A-Z]{5,},表示至少有5个大写字母)
{n,m}表示前面的字符串出现的次数大于n小于m,可以不连续
([A-Z]{5,10},表示有5-10个大写字母)
查找文件内包含小写字母的行
grep "[a-z]" 文件
查找行内至少有3个o的行
grep "o{3,}" 文件
查找包含以w开头,d结尾,中间至少两个o的行
grep "wo\{2,\}d" 文件
查找至少以两个wo开头,d结尾的内容
grep "[wo]\{2,\}d" 文件
查找有连续的o的行
grep "o*" 文件 (可以一个o都没有)
grep "oo*" 文件 (至少有一个)
扩展正则表达式的常见元字符
+ 重复一个或者一个以上的前一个字符(a+,表示至少一个a)
? 零个或者一个的前一个字符(a?,表示最多一个a)
| 使用或者(or)的方式找出多个字符
( ) 查找“组”字符串
( )+ 辨别多个重复的组
扩展正则表达式要用egrep
egrep "t(e|a)st" 文件 test、tast都能被查到
egrep "t(e|a)+st" 文件 teest、teast、taest、taast..
直接修改文件
sed -i "" 文件
把ONBOOT行内的no改成yes
sed -i "/ONBOOT/s/no/yes/g" 文件
删除UUID所在行
sed -i "/UUID/d" 文件
在第12行后面添加IPADDR=$IP
sed -i "12a IPADDR=$IP" 文件
删除第18行
sed -i "18d" 文件
把文件内所有ens33改成ens37
sed -i "s|ens33|ens37|" 文件
在option所在行的下一行添加subnet
sed -i "/option/a subnet" 文件
awk -F. '{print $2}' 文件
awk '{print $1}'
s="abcdefghijklmn"
s1=${变量名:0:2}
结果:ab
s2=${s:1:-1}
结果:bcdefghijklm
s3=${s:0-5:3}
结果:jkl
s4=${s:0-5:-3}
结果:jk
第二个参数为正数,作用是从左开始数
第二个参数为0-n,作用是从右开始保留n个
第三个参数为正数,作用是从前面开始保留的数量
第三个参数为负数,作用是从后面开始去掉的数量
统计字符串长度${#变量名}
乘方运算
vim mi.sh
#!/bin/bash
num=1
for ((i=0;$i<$2;i++))
do
num=$(($num*$1))
done
echo $num
sh mi.sh 2 3 结果是8
冒泡排序
vim mp.sh
#!/bin/bash
n=(3 2 4 5 1)
for ((i=${#n[@]};$i>1;i--))
do
for ((j=0;$j<$(($i-1));j++))
do
k=$(($j+1))
if [ ${n[$j]} -gt ${n[$k]} ]
then
m=${n[$j]}
n[$j]=${n[$k]}
n[$k]=$m
fi
done
done
for ((i=0;$i<${#n[@]};i++))
do
echo ${n[$i]}
done
#!/bin/bash
n=()
for ((i=0;i<=i;i++ ));do
read -p "请输入第 $(($i+1)) 个数字:" qw
if [ -z $qw ];then
break
fi
n[$i]=$qw
done
echo "排序前:${n[@]}"
l=${#n[@]}
for ((i=1;i<$l;i++))
do
for ((j=0;j<$(($l-$i));j++))
do
k=$(($j+1))
if [ ${n[$j]} -gt ${n[$k]} ]
then
t=${n[$j]}
n[$j]=${n[$k]}
n[$k]=$t
fi
done
done
echo "排序后:${n[@]}"
水仙花数:一个n位数,每个数位上数字的n次方加起来还等于原来的数
for ((i=100;$i<9999;i++))
do
sum=0
n=$i
for ((j=0;$j<${#i};j++))
do
a=$(($n%10))
s=1
for((k=0;$k<${#i};k++))
do
s=$(($s*$a))
done
sum=$(($sum+$s))
n=$(($n-$a))
n=$(($n/10))
done
if [ $sum = $i ]
then
echo $i
fi
done
#!/bin/bash
for ((i=100;i<10000;i++))
do
l=${#i}
s=0
for ((j=0;j<$l;j++))
do
n=${i:$j:1}
c=1
for ((k=0;k<$l;k++))
do
c=$(($c*$n))
done
s=$(($s+$c))
done
if [ $s -eq $i ]
then
echo $s
fi
done
乘法表
#for ((i=1;$i<10;i++))
#do
# for ((j=1;$j<=$i;j++))
# do
# echo -e "$j*$i=$(($j*$i))\t\c"
# done
# echo ""
#done
i=1
while [ $i -lt 10 ]
do
j=1
while [ $j -le $i ]
do
echo -e "$j*$i=$(($j*$i))\t\c"
let j++
done
echo ""
let i++
done
退出脚本
exit
退出循环
break