主要内容总结:
–shell脚本 .sh
–shell是基于系统的解释型语言,一般通过Linux,sh 或者 bash 来解释.
–#!/bin/bash 执行方法 bash 脚本名 ./脚本名(有可执行权限)
–开头指定命令解释器
–变量 变量名=值
–引号:‘’ 单引号内所有内容判断为字符串,“” 双引号内可以识别变量,`` 反引号内可以识别系统命令
–二元比较符: -eq,-gt,-lt,-ge,-le,-ne
–一元比较符: ==,!=,-z,-n
–文件比较符:-e 判断文件是否存在,-f 判断文件类型是否是普通文件,-d 判断文件类型是否是目录
–if 循环:
if [ 条件 ]
then
动作1
elif [ 条件2 ]
then
动作2
else
动作3
fi
–case 循环
case 变量 in
值1)
动作1
;;
值2)
动作2
;;
*)
动作3
esac
–while 循环
while [ 条件 ]
do
动作
done
–for 循环
for 变量名 in ``(区间)(系统命令)
do
动作
done
for((初始值;循环条件;递增值))
do
动作
done
–until 循环
until [ 退出循环条件 ]
do
动作
done
shell 脚本 .sh (Linux的脚本文件)
shell 是基于系统的解释型语言,一般是通过Linux sh或者bash来解释。
bat (Windows的脚本文件)
解释性 不需要编译 写起来方便(快) 运行慢(最难突破的点)
编译型 速度快 修改困难 扩展性差 预设定好的
解释语言与其相应的解释器:shell(一些bash sh文件) python(用python解释) Javascript java (JDK)
主要用来解释这些语言,解释成为电脑可以理解的语言
汇编语言可以看做是最底层的语言 可以直接使得计算机理解
编译型语言:C(代码量大,面对过程) C++
高级编程语言 C++ Java python
(高级编程语言)一个特性:面向对象
shell脚本学习
why?
因为很多服务器大多是Linux
而且shell脚本在Linux上面运行快
一个统一表结构的脚本例子
#!/bin/bash
#获取表的个数
rownum=` wc -l emp0228.txt | awk '{print $1}' `
#没一张表循环比较一次表结构
for((i=1;i<=$rownum;i++));
do
#获取每次比较的表名
table_name=` awk -v rn=$i 'NR==rn{print $1}' emp0228.txt `
#通过循环次数i每次循环获取一个表的表结构
old_table=` awk -v rn=$i 'NR==rn{print $0}' emp0228.txt `
new_table=` awk -v rn=$i 'NR==rn{print $0}' emp0301.txt `
#获取新老表结构的字段数
old_tab_col_cnt=` awk -v rn=$i 'NR==rn{print NF}' emp0228.txt `
new_tab_col_cnt=` awk -v rn=$i 'NR==rn{print NF}' emp0301.txt `
#记录旧表是第几个字段
old_col=0
#for循环遍历旧表字段
for o in $old_table;
do
#每次循环字段序号加一
let old_col+=1
#记录新表字段序号
new_col=0
#遍历新表字段
for n in $new_table;
do
#新表字段序号每次循环加一
let new_col+=1
#如果新老表正好遍历的字段序列一致则比较
if [ $old_col -eq $new_col ];
then
#如果列位置序号一致,列名或数据类型不相等一律更改成新列名和数据类型,匹配成功直接continue本次循环,modify要列名和字段类型分开比较过于复杂,这里选择删除老列增加新列代替修改
if [ $o != $n ];
then
echo "Alter table $table_name drop column $o;" >> modify.txt
echo "Alter table $table_name add $n;" >> modify.txt
continue
else
continue
fi
fi
if [ $new_col -eq $new_tab_col_cnt ]
then
#如果旧表遍历列序号大于新表总列数证明有删除列
if [ $old_col -gt $new_tab_col_cnt ]
then
echo "Alter table $table_name drop column $o;" >> modify.txt
fi
fi
if [ $old_col -eq $old_tab_col_cnt ]
then
if [ $new_col -gt $old_col ];
then
echo "Alter table $table_name add $n;" >> modify.txt
continue
fi
fi
done
done
done
shell
在开头指定命令解释器
用bash还是 sh 来执行
Q: “#!/bin/bash”的作用 ?
答:#!/bin/bash是shell脚本的第一行,称为释伴(shebang)行。这里#符号叫做hash,而! 叫做 bang。它的意思是命令通过 /bin/bash 来执行。
#!/bin/bash
可以不写,但是环境复杂的情况下一定要写
运行脚本
bash + 可执行文件
如果文件有可执行的权限,那么./文件名可以直接执行
./脚本名(脚本有可执行权限)
赋予权限
圈出那一行左边的意思是权限相关,首先是用户权限,然后是组的权限,最后是其他人的权限
r read
w write
x execute
赋予权限的语句
chmod 777 + 文件名
将可读可写可执行的所有权限赋给用户 用户组还有其他人
声明变量 变量名=值
创建一个shell脚本
就是创建一个sh文件
然后赋予可执行权限
shell脚本每次执行一行 所以不要将两个命令放在一行
但是可以在每个命令后面加个分号; 这样可以执行
shell没有缩进,但是跟python一样都是行处理的,每次执行一行命令
两个$可以写在一块
单引号内通通是字符串
双引号内可以有变量
反引号里面是命令执行的结果
#!/bin/bash
A="shell"
B="script"
echo '$A脚本'
echo $A$B(这样也可以执行)
[root@iZ8vbgw05auetj737q3v9rZ yx]# bash yx.sh
$A脚本
用了系统命令必须加反引号
[root@iZ8vbgw05auetj737q3v9rZ yx]# cat yx.sh
#!/bin/bash
A="date"
B=` date `
echo $A
echo $B
[root@iZ8vbgw05auetj737q3v9rZ yx]# bash yx.sh
date
Thu Mar 2 11:25:12 CST 2023
局部变量和全局变量
[root@iZ8vbgw05auetj737q3v9rZ yx]# cat yx.sh
#!/bin/bash
A=10
( A=20
echo $A)
echo $A
[root@iZ8vbgw05auetj737q3v9rZ yx]# bash yx.sh
20
10
用花括号{}修改全局变量
[root@iZ8vbgw05auetj737q3v9rZ yx]# cat test.sh
#!/bin/bash
A=10
{
A=20
echo $A
}
echo $A
[root@iZ8vbgw05auetj737q3v9rZ yx]# bash test.sh
20
20
使用子shell会处理更快 但是更乱
花括号确定变量的边界
[root@iZ8vbgw05auetj737q3v9rZ yx]# cat test.sh
#!/bin/bash
A=10
AB=20
echo ${A}B
[root@iZ8vbgw05auetj737q3v9rZ yx]# bash test.sh
10B
小括号一般用来运算
中括号表示条件更多 比如跟if搭配使用 注意 前后中间必须空格
[root@iZ8vbgw05auetj737q3v9rZ yx]# cat test.sh
#!/bin/bash
A=$((10+10))
AB=20
if [$A -eq $AB]
then
echo ${A}B
fi
[root@iZ8vbgw05auetj737q3v9rZ yx]# bash test.sh
20B
if 与then 不可以直接写在一行 加分号
echo -n打印不换行
没有声明的参数
Q: Bourne shell(bash) 中有哪些特殊的变量 ?
答:下面的表列出了Bourne shell为命令行设置的特殊变量。
内建变量 解释
$0 命令行中的脚本名字
$1 第一个命令行参数
$2 第二个命令行参数
…… …….
$9 第九个命令行参数
$# 命令行参数的数量
$* 所有命令行参数,以空格隔开
[root@iZ8vbgw05auetj737q3v9rZ yx]# cat test.sh
#!/bin/bash
echo $1$2$3$4
$1$2$3$4代表获取第1234个参数
[root@iZ8vbgw05auetj737q3v9rZ yx]# bash test.sh 10 20 30 40
10203040
[root@iZ8vbgw05auetj737q3v9rZ yx]# cat test.sh
#!/bin/bash
echo $1$2$3$4
echo $*
echo $#
$*代表获取所有参数
$#获取参数的个数
[root@iZ8vbgw05auetj737q3v9rZ yx]# bash test.sh 10 20 30 40
10203040
10 20 30 40
4
[root@iZ8vbgw05auetj737q3v9rZ yx]# bash test.sh 10 20 30 40 5
10203040
10 20 30 40 5
5
[root@iZ8vbgw05auetj737q3v9rZ yx]# cat test.sh
#!/bin/bash
echo $1$2$3$4
echo $*
echo $#
echo $0
$0代表获取到文件的名字
[root@iZ8vbgw05auetj737q3v9rZ yx]# bash test.sh 10 20 30 40 5
10203040
10 20 30 40 5
5
test.sh
提示入参,一般用来做交互
[root@iZ8vbgw05auetj737q3v9rZ yx]# cat test.sh
#!/bin/bash
read num
echo $num
打印输入的数据
[root@iZ8vbgw05auetj737q3v9rZ yx]# bash test.sh
10
10
[root@iZ8vbgw05auetj737q3v9rZ yx]# cat test.sh
#!/bin/bash
read -p"请输入一个数字:" num
echo $num
[root@iZ8vbgw05auetj737q3v9rZ yx]# bash test.sh
请输入一个数字:10
10
创建以及删除文件的脚本
[root@iZ8vbgw05auetj737q3v9rZ yx]# cat test.sh
#!/bin/bash
touch $1
read -p"是否删除$1[y/n]:" choose
if [ $choose == "y" ];
then
rm -rf $1
fi
Q: 在shell脚本中,如何测试文件 ?
答:test命令可以用来测试文件。基础用法如下表格:
Test 用法
-d 文件名 如果文件存在并且是目录,返回true
-e 文件名 如果文件存在,返回true
-f 文件名 如果文件存在并且是普通文件,返回true
-r 文件名 如果文件存在并可读,返回true
-s 文件名 如果文件存在并且不为空,返回true
-w 文件名 如果文件存在并可写,返回true
-x 文件名 如果文件存在并可执行,返回true
比较符
二元比较符(数值比较符):-eq, -gt, -lt, -ge, -le, -ne(not equal)
一元比较符(字符串比较符): == , !=, -z(zero空), -n(非空)
文件比较符:-e (判断文件是否存在);-f (判断文件类型是否是普通文件); -d(判断文件类型是否是目录);
#!/bin/bash
A=""
if [ -z $A ];
then echo "空"
fi
[root@iZ8vbgw05auetj737q3v9rZ yx]# bash a.sh
空
判断是否为目录
[root@iZ8vbgw05auetj737q3v9rZ yx]# cat a.sh
#!/bin/bash
A=""
if [ -d $1 ];
then echo "是目录"
else
echo "没有这个目录"
fi
[root@iZ8vbgw05auetj737q3v9rZ yx]# bash a.sh /home/yx
是目录
[root@iZ8vbgw05auetj737q3v9rZ yx]# bash a.sh 1.sh
没有这个目录
[root@iZ8vbgw05auetj737q3v9rZ yx]# bash a.sh /home
是目录
[root@iZ8vbgw05auetj737q3v9rZ yx]# bash a.sh /bin
是目录
[root@iZ8vbgw05auetj737q3v9rZ yx]# bash a.sh /
是目录
if的用法
if [ 条件 ]
then
命令1
命令2
…..
elseif [ 条件 ]
then
命令1
命令2
….
else
命令1
命令2
…..
fi
如果输入是一个目录,那么就切换到这个目录下面并且创建一个zbc.txt文件
如果输入是一个文件,那么就查看这个文件
其他情况下输入的话,那么就创建该文件。
[root@iZ8vbgw05auetj737q3v9rZ yx]# cat a.sh
#!/bin/bash
if [ -d $1 ];
then
cd $1
touch zbc.txt
elif [ -f $1 ];
then
cat $1
else
touch $1
fi
[root@iZ8vbgw05auetj737q3v9rZ yx]# cd /
[root@iZ8vbgw05auetj737q3v9rZ /]# ls
1.gz 3.txt dev home LS proc srv var zbc.txt
1.sh bin etc lib media root sys wyh zyl
1.txt boot fjh1 lib64 mnt run tmp yx zyl1
2.txt csd.txt fjh.sh lost+found opt sbin usr yx1 ZZ
[root@iZ8vbgw05auetj737q3v9rZ /]# cd -
/home/yx
[root@iZ8vbgw05auetj737q3v9rZ yx]# bash a.sh 1.sh
#!/bin/bash
for i in ` cat for.txt `
do
echo -n "$i "
if [ $i -eq 15 ];
then echo " "
fi
done
case循环
case 变量 in
值1)
命令1
命令2
…..
;;
值2)
命令1
命令2
……
最后命令
;;
*) // *)代表else
命令1...
esac
[root@iZ8vbgw05auetj737q3v9rZ yx]# cat case.sh
#!/bin/bash
case $1 in
c)
echo "蔡徐坤"
;;
w)
echo "王俊凯"
;;
*)
echo "没这个人"
esac
[root@iZ8vbgw05auetj737q3v9rZ yx]# bash a.sh c
a.sh: line 5: [-z: command not found
a.sh: line 9: echo没有这个目录: command not found
[root@iZ8vbgw05auetj737q3v9rZ yx]# bash case.sh c
蔡徐坤
[root@iZ8vbgw05auetj737q3v9rZ yx]# bash case.sh w
王俊凯
[root@iZ8vbgw05auetj737q3v9rZ yx]# bash case.sh 1
没这个人
也可以用以下这种方式
[root@iZ8vbgw05auetj737q3v9rZ yx]# cat case.sh
#!/bin/bash
case $1 in
c|C)
echo "蔡徐坤"
;;
w|W)
echo "王俊凯"
;;
*)
echo "没这个人"
esac
while循环
while [ 条件 ]
do
命令…
done
while true 会一直执行
比如判断某个文件是否存在,文件存在的话就执行某个操作
while true 一定要加休眠
注意要使用let 另外式子不要加空格(别随手打空格)
可以写成这样,但是不要加空格
let a+=i
[root@iZ8vbgw05auetj737q3v9rZ yx]# cat while.sh
#!/bin/bash
i=1
a=0
while [ $i -le 100 ];
do
let a=a+i
let i++
done
echo $a
[root@iZ8vbgw05auetj737q3v9rZ yx]# bash while.sh
5050
-o or 或者
-a and 并且
RANDOM是一个随机数
[root@iZ8vbgw05auetj737q3v9rZ yx]# cat dubo.sh
#!/bin/bash
num=$[RANDOM%5]
let num=$num+1
read -p "请猜测骰子的单双[d/s]:" choose
echo $num
if [ $choose == "d" ];
then
if [ $num -eq 1 -o $num -eq 3 -o $num -eq 5 ]
then
echo "猜对了,奖励一巴掌"
else
echo "猜错了,倾家荡产"
fi
else
if [ $num -eq 2 -o $num -eq 4 -o $num -eq 6 ]
then
echo "猜对了,奖励一巴掌"
else
echo "猜错了,倾家荡产"
fi
fi
[root@iZ8vbgw05auetj737q3v9rZ yx]# bash dubo.sh
请猜测骰子的单双[d/s]:d
4
猜错了,倾家荡产
[root@iZ8vbgw05auetj737q3v9rZ yx]# bash dubo.sh
请猜测骰子的单双[d/s]:s
4
猜对了,奖励一巴掌
[root@iZ8vbgw05auetj737q3v9rZ yx]# bash dubo.sh
请猜测骰子的单双[d/s]:d
3
猜对了,奖励一巴掌
[root@iZ8vbgw05auetj737q3v9rZ yx]# bash dubo.sh
请猜测骰子的单双[d/s]:s
2
猜对了,奖励一巴掌
[root@iZ8vbgw05auetj737q3v9rZ yx]# cat dubo.sh
#!/bin/bash
read -p "输入充值金额:" conis
while true;
do
num=$[RANDOM%5]
let num=$num+1
read -p "请猜测骰子的单双[d/s]:" choose
echo $num
if [ $choose == "d" ];
then
if [ $num -eq 1 -o $num -eq 3 -o $num -eq 5 ]
then
let conis++
echo "猜对了,奖励一巴掌"
else
let conis=$conis-1
echo "猜错了,倾家荡产"
fi
else
if [ $num -eq 2 -o $num -eq 4 -o $num -eq 6 ]
then
let conis++
echo "猜对了,奖励一巴掌"
else
let conis=$conis-1
echo "猜错了,倾家荡产"
fi
fi
if [ $conis -lt 1 ]
then
echo "没钱玩什么玩"
break
fi
read -p "还剩$conis元搏一搏?[y/n]:" test
if [ $test == n ];
then
echo "拿$conis元收手跑路"
break
fi
done
[root@iZ8vbgw05auetj737q3v9rZ yx]# bash dubo.sh
输入充值金额:1
请猜测骰子的单双[d/s]:d
3
猜对了,奖励一巴掌
还剩2元搏一搏?[y/n]:n
拿2元收手跑路
a++ a–都可以使用,但是要记得用let
[root@iZ8vbgw05auetj737q3v9rZ yx]# cat sr.sh
#!/bin/bash
a=1
let a--
echo $a
[root@iZ8vbgw05auetj737q3v9rZ yx]# bash sr.sh
0
相当于自己可以看得见结果,这样无论什么情况都是正确的
[root@iZ8vbgw05auetj737q3v9rZ yx]# cat dubo.sh
#!/bin/bash
read -p "输入充值金额:" conis
while true;
do
num=$[RANDOM%5]
let num=$num+1
#read -p "请猜测骰子的单双[d/s]:" choose
echo $num
if [ $num -eq 1 -o $num -eq 3 -o $num -eq 5 ]
then
choose=d
else
choose=s
fi
if [ $choose == "d" ];
then
if [ $num -eq 1 -o $num -eq 3 -o $num -eq 5 ]
then
let conis++
echo "猜对了,奖励一巴掌"
else
let conis=$conis-1
echo "猜错了,倾家荡产"
fi
else
if [ $num -eq 2 -o $num -eq 4 -o $num -eq 6 ]
then
let conis++
echo "猜对了,奖励一巴掌"
else
let conis=$conis-1
echo "猜错了,倾家荡产"
fi
fi
if [ $conis -lt 1 ]
then
echo "没钱玩什么玩"
break
fi
#read -p "还剩$conis元搏一搏?[y/n]:" test
echo "还剩$conis元"
test=y
if [ $test == n ];
then
echo "拿$conis元收手跑路"
break
fi
sleep 1s
done
用一个美元符号和方括号($[ 表达式 ])执行计算
[root@iZ8vbgw05auetj737q3v9rZ yx]# cat sr.sh
#!/bin/bash
test=$[ 16 + 4 ]
echo $test
[root@iZ8vbgw05auetj737q3v9rZ yx]# bash sr.sh
20
while循环的优点:
可以使用while true
for循环 知道自己想要循环的范围或者次数
多行输入的方式
可以使用 空格+回车 进行
使用done结束输入
[root@iZ8vbgw05auetj737q3v9rZ yx]# for i in {1..3}
> do echo "print $i"
> done
print 1
print 2
print 3
for循环
for 变量名 in ``(区间)(系统命令)
do
动作
done
[root@iZ8vbgw05auetj737q3v9rZ yx]# seq 5
1
2
3
4
5
[root@iZ8vbgw05auetj737q3v9rZ yx]# echo {1..10}
1 2 3 4 5 6 7 8 9 10
[root@iZ8vbgw05auetj737q3v9rZ yx]# echo {5..10}
5 6 7 8 9 10
带步长的序列
[root@iZ8vbgw05auetj737q3v9rZ yx]# echo {5..15..2}
5 7 9 11 13 15
[root@iZ8vbgw05auetj737q3v9rZ yx]# cat sr.sh
#!/bin/bash
for i in `ls /home/yx`
do
read -p "你想要删除$i吗:" choose
if [ $choose == y ];
then rm -rf $i
else
continue
fi
done
执行结果
[root@iZ8vbgw05auetj737q3v9rZ yx]# bash sr.sh
你想要删除1.sh吗:n
你想要删除a.sh吗:n
你想要删除case.sh吗:n
你想要删除db.sh吗:n
你想要删除dubo.sh吗:n
你想要删除dugou.sh吗:n
你想要删除for1.sh吗:n
你想要删除for.txt吗:n
你想要删除if.sh吗:n
你想要删除newdb.txt吗:n
你想要删除qaz.txt吗:n
你想要删除sr.sh吗:n
你想要删除test_1.txt吗:n
你想要删除test.sh吗:n
你想要删除test.txt吗:n
你想要删除txt吗:n
你想要删除while.sh吗:n
你想要删除yx.sh吗:n
你想要删除zaq.txt吗:n
你想要删除zz.txt吗:n
每隔3秒钟拿出1.txt的第一行,然后输出到一个新的文件
[root@iZ8vbgw05auetj737q3v9rZ yx]# cat for2.sh
#!/bin/bash
for i in 1 2 3 4 5
do
awk 'NR==1{print $0}' 1.txt >> 1.txt.log
sleep 3s
done
#下面是运行之后的结果
[root@iZ8vbgw05auetj737q3v9rZ yx]# cat 1.txt.log
已完成10张表的数据插入!
已完成10张表的数据插入!
已完成10张表的数据插入!
已完成10张表的数据插入!
已完成10张表的数据插入!
打印1-100
记得是两个括号
[root@iZ8vbgw05auetj737q3v9rZ yx]# cat for3.sh
#!/bin/bash
for((i=1;i<=100;i++))
do
echo $i
done
until 循环
[root@iZ8vbgw05auetj737q3v9rZ yx]# cat until.sh
#!/bin/bash
i=1
until [ $i -eq 101 ]
do
echo $i
let i++
done
[root@iZ8vbgw05auetj737q3v9rZ yx]# bash until.sh
1
2
3
4
5
....后面省略了
使用seq 的时候加空格 seq与后面数字之间一定要加空格(佛了)
[root@iZ8vbgw05auetj737q3v9rZ yx]# cat sq.sh
#!/bin/bash
for i in ` seq 3 `;do
for j in ` seq $i `;do
echo -n "* "
done
echo " "
done
[root@iZ8vbgw05auetj737q3v9rZ yx]# bash sq.sh
*
* *
* * *
[root@iZ8vbgw05auetj737q3v9rZ yx]# cat sq.sh
#!/bin/bash
for i in ` seq 3 `;do
let a=4-$i
for j in ` seq $a `;do
echo -n "* "
done
echo " "
done
[root@iZ8vbgw05auetj737q3v9rZ yx]# bash sq.sh
* * *
* *
*