Shell脚本速通指南(比小米Su7还快)

前言:基础

Centos默认的脚本解析器是bash(bash也是软连接文件sh -> bash)

脚本第一行声明bash脚本:#!/bin/bash

脚本执行

1、sh+脚本名称

2、给脚本赋予权限chmod u+x 脚本名称,绝对路径and相对路直接径运行

一、变量

需要sorce /etc/profilesorce ~/.bashrc重新加载环境变量

printenv输出当前环境变量

1、全局变量 /etc/profile

2、局部变量~/.bashrc

3、定义自定义变量export Su7=21.69,输出变量 echo $Su7

1、关于自定义变量

记住:用户登录之后开启一个解释器bash(-号),当启动一个脚本文件;重新启动一个bash(二号)去执行脚本,二号bash是一号子bash。

1
2
3
4
5
6
7
8
sh复制代码[shishu@hadoop1]$ export B=su7
[shishu@hadoop1]$ echo $B
[shishu@hadoop1]$ cat helloworld.sh
echo "helloworld'
echo $B
[shishu@hadoop1]$ sh helloworld.sh
helloword
su7

如果再去开一个窗口,就意味着开了一个新的bash,不能继承这个同级别的bash变量。

2、特殊变量 $$#

$n 功能描述:n为数字,$0代表该脚本名称,$1-$9代表第一到第九个参数,十以上的参数,十以上的参数需要用大括号包含,如${10}

$# 传参数个数

1
2
3
4
5
6
7
8
9
shell复制代码[root@clb1 shell]# cat teshu.sh
#!/bin/bash
#传参个数
echo $#
#参数输出
echo "$0 $1 $2"
[root@clb1 shell]# sh teshu.sh xiaomi su7
2
teshu.sh xiaomi su7

3、特殊变量 $*$@

$*

功能描述:这个变量代表命令行中所有的参数,$*把所有的参数看成一个整体

$@

功能描述:这个变量也代表命令行中所有的参数,不过$@把每个参数区分对待

4、特殊变量 $?

$?

功能描述:最后一次执行的命令的返回状态。如果这个变量的值为0,证明上一个命令正确执行;如果这个$?变量的值为非0(具体是哪个数,由命令自己来决定),则证明上一个命令执行不正确了。

1
sh复制代码echo $?

二、数学计算

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
sh复制代码#!/bin/bash
A=100
B=2
#第一种写法
C=$((A+B))
#第二种
D=$[A+B]
#第三种
E=`expr $A + $B`
echo $E

#综合运算(2+3)*5
F=$[(2+3)*5]
#expr `expr 2+3` * 5
echo $F

三、条件判断

1、常用判断条件

(1) 两个整数之间比较

  • = 字符串比较
  • -lt 小于(less than)
  • -le 小于等于(less equal)
  • -eq 等于(equal)
  • -ne 不等于(Not equal)
  • -gt 大于(greater than)
  • -ge 大于等于(greater equal)

(2) 按顺文件权限进行判断

-r 有读的权限(read)

-w 有写的权限(write)

-x 有执行的权限(execute)

(3) 按顺文件关型进行判断

-f 文件存在并且是一个常规的文件(file)

-e 文件存在(existence)

-d 文件存在并是一个目录(directory)

2 、练习实操

(1) 逻辑语句 &&||

&& 前面条件成立,后面语句才会执行(逻辑与)

|| 前面条件不成立,后面语句才会执行(逻辑或)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
sh复制代码[root@clb1 shell]# cat luoji.sh
#!/bin/bash
#&& 逻辑与 和 逻辑或
echo $#
[ $# -gt 2 ] && echo "参数的个数大于2"
[ $# -lt 2 ] || echo "参数的个数大于2----"
[root@clb1 shell]# sh luoji.sh 1 2 3
3
参数的个数大于2
参数的个数大于2----
[root@clb1 shell]# sh luoji.sh 1 2
2
参数的个数大于2----
[root@clb1 shell]# sh luoji.sh 1
1
(2) 利用命令的执行结果进行判断

判断用户是否存在,创建用户

参考:echo $? 输出的0 和 1 ,表示Y 与 F

1
2
3
4
sh复制代码#!/bin/bash
#如果用户zhangsan不存在,则添加用户zhangsan
id zhangsan &> /dev/null && echo "zhangsan用户存在,不用添加"
id zhangsan &> /dev/null || useradd zhangsan

四、流程控制

1、if 判断

基本格式

注意事项: (1) [ 条件判断式 ],中括号和条件判断式之间必须有空格

(2) if后要有空格

1
2
3
4
5
6
7
8
9
10
sh复制代码if [ 条件判断句 ];then
  程序
fi

#或者

if [ 条件判断句 ]
   then
  程序
fi

案例:判断年龄

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
sh复制代码[root@clb1 shell]# cat if.sh
#!/bin/bash
if [ $1 -lt 18 ];then
   echo "未成年"
elif [ $1 -ge 18 -a $1 -le 30 ];then
   echo "青年"
else
   echo "中老年"
fi
[root@clb1 shell]# sh if.sh 22
青年
[root@clb1 shell]# sh if.sh 33
中老年
[root@clb1 shell]# sh if.sh 3
未成年

2、case语句

基本格式

注意事项

1)case行尾必须为单词“in”,每一个模式匹配必须以右括号 )结束

2)双分号 ;; 表示命令序列结束,相当于java中的break。

3)最后的*)表示默认模式,相当于java中的default。

1
2
3
4
5
6
7
8
9
10
11
sh复制代码case $变量名 in
“值1”)
如果变呈的值等于值1,则执行程序1
;;
“值2”)
如果变星的值等于值2,则执行程序2
;;
*)
如果变量的值都不是以上的值,则执行此程序
;;
esac

案例:判断输入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
sh复制代码[root@clb1 shell]# cat case.sh
#!/bin/bash
case $1 in
"start")
echo "你输入的是start"
;;
"stop")
echo "你输入的是stop"
;;
*)
echo "你输入的是其他"
;;
esac
[root@clb1 shell]# sh case.sh stop
你输入的是stop
[root@clb1 shell]# sh case.sh start
你输入的是start
[root@clb1 shell]# sh case.sh st
你输入的是其他

3、for 循环

(1) 用法一

基础语法

1
2
3
4
sh复制代码for ((初始值;循环控制条件;变量变化))
do
程序
done

案例:1到100的和

1
2
3
4
5
6
7
sh复制代码#!/bin/bash

for ((i=0;i<=100;i++));do
s=$[$s+$i]
done

echo "1到100的和是$s"
(2) 用法二

基础语法

1
2
3
4
sh复制代码for 变量 in 值1 值2 值3...
do
程序
done

案例 1:1到100的和

1
2
3
4
5
6
sh复制代码[root@clb1 shell]# cat sum100.2.sh
#!/bin/bash
for i in {1..100};do
s=$[$s+$i]
done
echo "1到100的和是$s"
1
2
3
4
5
6
sh复制代码[root@clb1 shell]# cat sum100.2.sh
#!/bin/bash
for i in `seq 1 100`;do
s=$[$s+$i]
done
echo "1到100的和是$s"

案例 2:显示/root下面所有文件名称

案例告诉我们,在for循环中,空格和换行都可以进行分割字符

1
2
3
4
5
sh复制代码[root@clb1 shell]# cat file.sh
#!/bin/bash
for i in `ls /root`;do
echo $i
done

案例 3:区分$*$@

只有$*$@带上双引号代表的意义才不同

踩坑提示

1
2
3
4
> bash复制代码echo "我是你的"
> echo"我是你的"
>
>

在脚本中echo后面有没有空格的含义是不一样的。

如果没有空格整个语句会被认为是一条命令。例如下面的报错

1
2
3
4
5
> markdown复制代码qufen.sh:行3: echo传入脚本的参数是:qqq: 未找到命令
> qufen.sh:行3: echo传入脚本的参数是:www: 未找到命令
> --------------
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
sh复制代码[root@clb1 shell]# cat qufen.sh
#先测试$*
for i in "$*";do
echo "传入脚本的参数是:$i"
done
echo "--------------"
#测试$@
for j in "$@";do
echo "传入脚本的参数是:$j"
done
[root@clb1 shell]# sh qufen.sh 123 321
传入脚本的参数是:123 321
--------------
传入脚本的参数是:123
传入脚本的参数是:321

4、while循环

案例 :1到100的和

1
2
3
4
5
6
7
8
9
10
11
12
sh复制代码[root@clb1 shell]# cat sum100.3.sh
#!/bin/bash
i=1
sum=0
while [ $i -le 100 ];do
let sum=sum+i
#这行代码也可以写成:sum=$[$sum+$i]
let i++
done
echo "从1到100的和是:$sum"
[root@clb1 shell]# bash sum100.3.sh
从1到100的和是:5050

五、read读取控制台输入

1、基础语法

read(选项)(参数)

选项:

-p:指定读取值时的提示符

-t: 指定读取值时等待的时间(秒)

参数:

变量:指定读取值的变量名

2、练习实操

案例 : 求1到输入数字的和

1
2
3
4
5
6
7
8
9
10
11
12
13
sh复制代码[root@clb1 shell]# cat sumx.sh
#!/bin/bash
read -p "请输入的数字" x
i=1
sum=0
while [ $i -le $x ];do
let sum=sum+i
let i++
done
echo "1到$x的和是$sum"
[root@clb1 shell]# sh sumx.sh
请输入的数字10
1到10的和是55

for循环

1
2
3
4
5
6
7
sh复制代码#!/bin/bash
read -t 3 -p "请在3秒内请输入的数字" x
sum=0
for ((i=1;$i<=$x;i++));do
let sum=sum+i
done
echo "1到$x的和是$sum"

六、函数

1、系统函数

(1)basename

基本语法

basename命令会删掉所有的前缀包括最后一个(/)字符

也可以指定后缀,来切除末尾

1
2
3
4
sh复制代码[root@clb1 shell]# basename /root/shell/sumx.sh
sumx.sh
[root@clb1 shell]# basename /root/shell/sumx.sh .sh
sumx
(2)dirname

基本语法

dirname 文件绝对路径

功能描述:从给定的包含绝对路径的文件名中去除文件名(非目录的部分)然后返回剩下的路径(目录的部分)

1
2
sh复制代码[root@clb1 shell]# dirname /root/shell/sumx.sh
/root/shell
(3)综合案例

更换txt文件为sh文件

1
2
3
4
5
6
7
8
9
10
11
sh复制代码[root@clb1 shell]# cat zhixing.sh
#!/bin/bash
i=0
for f in `ls /root/shell/*.txt`;do
basename=`basename $f .txt`
file=$basename".sh"
mv $f $file
let i++
echo "已更改$i个文件"
echo "本次已经修改源文件$f变为$file"
done

image-20240330180502761

2、自定义函数

基本用法

1、必须在调用函数地方之前,先声明函数,shel脚本是逐行运行。不会像其它语言一样先编译。 2、函数返回值,只能通过$?系统变量获得,可以显示加:return返回,如果不加,将以最后一条命令运行结果,作为返回值。return后跟数值n(0-255)

案例练习1:自定义两数之和sum()

利用result承接输入值,利用echo $?输出。但是return后跟数值n(0-255)有范围,所以建议用下面优化版本。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
sh复制代码[root@clb1 shell]# cat zidingyi.1.sh
#!/bin/bash
#自定义函数
function sum(){
let s=$1+$2
return $s
}
sum 100 200
echo $?
[root@clb1 shell]# sh zidingyi.1.sh
44
[root@clb1 shell]# cat zidingyi.2.sh
#!/bin/bash
#自定义函数
function sum(){
let s=$1+$2
return $s
}
sum 10 200
echo $?
[root@clb1 shell]# sh zidingyi.2.sh
210

优化版本

1
2
3
4
5
6
7
8
9
10
11
sh复制代码[root@clb1 shell]# cat zidingyi.3.sh
#!/bin/bash
#自定义函数
function sum(){
let s=$1+$2
echo $s
}
result=`sum 100 200`
echo $result
[root@clb1 shell]# sh zidingyi.3.sh
300
案例练习2:求数据的阶乘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
sh复制代码[root@clb1 shell]# cat jiecheng.sh
#!/bin/bash
if [ $1 -eq 1 ];then
echo "参数错误,程序退出!"
exit 3 #返回的状态码 也就是echo #?输出的
fi
function jiecheng(){
n=$1
if [ $n -le 1 ];then
echo 1 #当n=1的时候,函数的返回值
return 0 #返回的执行状态
elif [ $n -gt 1 ];then
let pre_n=$n-1
temp=$(jiecheng $pre_n)
let result=n*temp
echo $result
return 0
fi
}
jiecheng $1
[root@clb1 shell]# sh jiecheng.sh 5
120

七、Shell工具

1、cut

1
2
3
4
sh复制代码[root@clb1 shell]# echo $PATH | cut -d : -f1
/usr/local/sbin
[root@clb1 shell]# grep "/bin/bash$" /etc/passwd |cut -d : -f1
root

2、awk

1
2
3
4
sh复制代码[root@clb1 shell]# awk -F ":" 'BEGIN{print "username,shell"} $NF ~ "/bin/bash$"{print $1","$NF} END{print "END"}' /etc/passwd
username,shell
root,/bin/bash
END

案例分享

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

0%