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

5,334 阅读4分钟

前言:基础

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

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

脚本执行

1、sh+脚本名称

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

脚本环境准备

修改vimrc文件,达到控制vim创建,编辑文件的动作

  • 当前用户家目录下 ~/.vimrc
  • 放在/etc/vimrc
" 2024/*/*新增,编辑sh文件默认开头

set ignorecase
autocmd BufNewFile *.py,*.cc,*.sh,*.java exec ":call SetTitle()"
func SetTitle()
    if expand("%:e") == 'sh'
        call setline(1, "#!/bin/bash")
        call setline(2, "##############################################################")
        call setline(3, "# File Name:".expand("%"))
        call setline(4, "# Version:V1.0")
        call setline(5, "# Author: shishuwu")
        call setline(6, "# Organization: GTS")
        call setline(7, "# Desc:")
        call setline(8, "##############################################################")
        call setline(9, " ")
    endif
endfunc

一、变量

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

printenv输出当前环境变量

1、全局变量 /etc/profile

2、局部变量~/.bashrc

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

1、关于自定义变量

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

[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}

$# 传参数个数

[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(具体是哪个数,由命令自己来决定),则证明上一个命令执行不正确了。

echo $?

二、数学计算

#!/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) 逻辑语句 &&||

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

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

[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

#!/bin/bash
#如果用户zhangsan不存在,则添加用户zhangsan
id zhangsan &> /dev/null && echo "zhangsan用户存在,不用添加"
id zhangsan &> /dev/null || useradd zhangsan

四、流程控制

1、if 判断

基本格式

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

(2) if后要有空格

if [ 条件判断句 ];then
    程序
fi#或者if [ 条件判断句 ]
    then
    程序
fi

案例:判断年龄

[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。

case $变量名 in
  “值1”)
    如果变呈的值等于值1,则执行程序1
    ;;
  “值2”)
    如果变星的值等于值2,则执行程序2
    ;;
  *)
    如果变量的值都不是以上的值,则执行此程序
    ;;
esac

案例:判断输入

[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) 用法一

基础语法

for ((初始值;循环控制条件;变量变化))
 do
    程序
 done

案例:1到100的和

#!/bin/bash

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

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

基础语法

for 变量 in 值1 值2 值3...
 do
    程序
 done

案例 1:1到100的和

[root@clb1 shell]# cat sum100.2.sh
#!/bin/bash
for i in {1..100};do
    s=$[$s+$i]
done
echo "1到100的和是$s"
[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循环中,空格和换行都可以进行分割字符

[root@clb1 shell]# cat file.sh
#!/bin/bash
for i in `ls /root`;do
    echo $i
done

案例 3:区分$*$@

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

踩坑提示

echo "我是你的"
echo"我是你的"

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

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

qufen.sh:行3: echo传入脚本的参数是:qqq: 未找到命令
qufen.sh:行3: echo传入脚本的参数是:www: 未找到命令
--------------
[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的和

[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到输入数字的和

[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循环

#!/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命令会删掉所有的前缀包括最后一个(/)字符

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

[root@clb1 shell]# basename /root/shell/sumx.sh
sumx.sh
[root@clb1 shell]# basename /root/shell/sumx.sh .sh
sumx
(2)dirname

基本语法

dirname 文件绝对路径

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

[root@clb1 shell]# dirname /root/shell/sumx.sh
/root/shell
(3)综合案例

更换txt文件为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)有范围,所以建议用下面优化版本。

[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

优化版本

[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:求数据的阶乘
[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

[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

[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

案例分享