Shell概述
什么是Shell
Shell是一个用C语言编写的程序,它是用户使用Linux的桥梁。Shell 既是一种命令语言,又是一种程序设计语言。
Shell是指一种应用程序,这个应用程序提供了一个界面,用户通过这个界面访问操作系统内核的服务。
![image-20221107211833782](Linux Shell编程/image-20221107211833782.png)
什么是Shell脚本
Shell脚本,是一种为shell编写的脚本程序。
业界所说的shell, 通常都是指shell脚本,但是shell 和 shell 脚本是两个不同的概念。
Shell的环境
Shel 编程跟 JavaScript、php 编程一样,只要有一个能编写代码的文本编辑器和一个能解释执行的脚本解释器就可以了
Linux 的 Shell 种类众多,常见的有:
Bourne Shell: /usr/bin/sh
或/bin/sh
Bourne Again Shell: /bin/bash
其中Bash在日常工作中被广泛使用, 同时也是大多数Linux系统默认的Shell
一般情况下人们并不区分Bourne Shell和Bourne Again Shell, 所以像#!/bin/sh
也可以改成#!/bin/bash
#!
表示告诉系统其后路径所指定的程序就是解析脚本文件的Shell程序
Shell脚本入门
脚本格式
脚本#!/bin/bash
开头, 表示指定解析器
脚本执行的三种方式
首先创建一个简单的Shell脚本, 用于输出"helloworld"
复制 [root@localhost herry]# touch helloworld.sh
[root@localhost herry]# vim helloworld.sh
[root@localhost script]# cat helloworld.h
#!/bin/bash
a="helloworld"
echo $a
1.bash或sh + 脚本路径
sh + 脚本的相对路径或绝对路径
复制 [root@localhost herry]# sh ./helloworld.sh
helloworld
复制 [root@localhost herry]# sh /home/herry/script/helloworld.sh
helloworld
bash + 脚本的相对路径或绝对路径
复制 [root@localhost herry]# bash helloworld.sh
helloworld
复制 [root@localhost herry]# bash /home/herry/script/helloworld.sh
helloworld
2.直接输入脚本的路径执行
首先赋予helloworld.sh可执行权限
复制 [root@localhost herry]# chmod +x helloworld.sh
然后再执行脚本, 以下分别使用相对路径和绝对路径执行
复制 [root@localhost script]# ./helloworld.h
helloworld
复制 [root@localhost script]# /home/herry/script/helloworld.h
helloworld
3.在脚本路径前加上.
或者source
此处将helloworld.sh脚本文件内容修改成如下所示:
复制 [root@localhost script]# cat helloworld.h
#!/bin/bash
echo $my_var
前两种方式都是在当前Shell中打开一个子Shell来执行脚本, 脚本执行完毕后, 则子Shell关闭, 回到父Shell中
以下代码使用前两种方式执行脚本, 均无任何输出, 这是因为$my_var变量作用于父Shell, 子shell是无法访问该变量的, 若想访问则需使用关键字export
将该变量定义成全局变量。
复制 [root@localhost script]# my_var="helloworld"
[root@localhost script]# ./helloworld.h
[root@localhost script]# bash ./helloworld.h
[root@localhost script]# export my_var
[root@localhost script]# ./helloworld.h
helloworld
而第三种方式可以使用当前Shell来执行脚本, 而无需新打开一个子Shell, 因此$my_var
变量是可以访问的
复制 [root@localhost script]# . helloworld.h
helloworld
变量
1.系统预定义变量
常用系统变量
$HOME
、$PWD
、$SHELL
、$USER
等等
使用实例
复制 [root@localhost herry]# echo $HOME
/root
复制 [root@localhost herry]# set
ABRT_DEBUG_LOG=/dev/null
BASH=/usr/bin/bash
BASHOPTS=checkwinsize:cmdhist:expand_aliases:extglob:extquote:force_fignore:histappend:interactive_comments:progcomp:promptvars:sourcepath
BASH_ALIASES=()
BASH_ARGC=()
BASH_ARGV=()
BASH_CMDS=()
2.自定义变量
基本语法
定义变量: 变量名=变量值 (注意:等号前后不能有空格)
声明静态变量: readonly 变量名
(此变量不能unset)
变量定义规则
变量名称由字母、数字和下划线组成, 不能以数字开头
在bash中, 变量默认为字符串类型, 无法进行数值运算
使用实例
1.给变量A赋值
复制 [root@localhost script]# a=5
[root@localhost script]# echo $a
5
2.撤销变量A
复制 [root@localhost script]# unset a
[root@localhost script]# echo $a
3.声明静态变量b, 不能unset
复制 [root@localhost script]# readonly b=1
[root@localhost script]# b=9
bash: b: 只读变量
[root@localhost script]# echo $b
1
4.在bash中变量默认类型均为字符串类型, 无法进行数值运算
复制 [root@localhost script]# c=1+1
[root@localhost script]# echo $c
1+1
5.将变量提升为全局变量, 可供其他Shell使用
复制 [root@localhost script]# cat helloworld.h
#!/bin/bash
echo $my_var
[root@localhost script]# export my_var="helloworld"
[root@localhost script]# ./helloworld.h
helloworld
3.特殊变量
$n
n为数字, $0
表示该脚本的名称, $1
-$9
代表第一到第九个参数, 第十及以以上的参数要用大括号包含, 如${10}
复制 [root@localhost script]# cat test.sh
#!/bin/bash
echo '===$n==='
echo $0
echo $1
echo $2
[root@localhost script]# chmod 777 test.sh
[root@localhost script]# ./test.sh henry 666
===$n===
./test.sh
henry
666
[root@localhost script]# /home/herry/script/test.sh henry 666
===$n===
/home/herry/script/test.sh
henry
666
$#
$#
表示获取输入参数的个数, 常用于循环以及判断参数个数是否正确
复制 [root@localhost script]# cat test.sh
#!/bin/bash
echo '===$n==='
echo $0
echo $1
echo $2
echo '===$#==='
echo $#
复制 [root@localhost script]# ./test.sh henry 666
===$n===
./test.sh
henry
666
===$#===
2
$*
、$@
$@
: 将所有的参数看成一个列表, 后续可用于遍历
复制 [root@localhost script]# cat test.sh
#!/bin/bash
echo '===$n==='
echo $0
echo $1
echo $2
echo '===$#==='
echo $#
echo '===$*==='
echo $*
echo '===$@==='
echo $@
[root@localhost script]# ./test.sh a b c d e
===$n===
./test.sh
a
b
===$#===
5
===$*===
a b c d e
===$@===
a b c d e
$?
$?
表示最后一次执行命令的返回状态。若值为0, 表示上一个命令执行正确; 若值非0, 表示上一个命令执行错误
复制 [root@localhost script]# ./test.sh
===$n===
./test.sh
===$#===
0
===$*===
===$@===
[root@localhost script]# echo $?
0
[root@localhost script]# test.sh
bash: test.sh: 未找到命令...
[root@localhost script]# echo $?
127
运算符
运算表达式
使用实例
复制 [root@localhost script]# vim add.sh
[root@localhost script]# chmod +x add.sh
[root@localhost script]# cat add.sh
sum=$[$1+$2]
echo $sum
[root@localhost script]# ./add.sh 1 2
3
复制 [root@localhost script]# echo $((1+5))
6
[root@localhost script]# echo $[1+5]
6
条件判断
基本语法
[ condition ]
(==注意condition前后两边要有空格==)
与其他编程语言不同的是, 条件为True时, echo $?
返回值为0; 条件为False时, echo $?
返回值为1;
常用判断条件
1.整数之间的比较
2.文件权限判断
3.文件类型判断
使用实例
1.判断整数之间的大小
复制 [root@localhost herry]# test 1=1
[root@localhost herry]# echo $?
0
[root@localhost herry]# [ 1 = 1 ]
[root@localhost herry]# echo $?
0
[root@localhost herry]# [ 1 = 2 ]
[root@localhost herry]# echo $?
1
[root@localhost herry]# [ 1 != 2 ]
[root@localhost herry]# echo $?
0
[root@localhost script]# [ 1 -lt 2 ]
[root@localhost script]# echo $?
0
注意: 等号两边也得有空格, 不然会报错
2.判断shell.sh文件是否有可执行权限
复制 [root@localhost script]# [ -x shell.sh ]
[root@localhost script]# echo $?
1
3.判断 /home/herry/script/shell.sh
文件是否存在
复制 [root@localhost script]# [ -f /home/herry/script/shell.sh ]
[root@localhost script]# echo $?
0
4.多条件判断( &&
表示前一条命令执行成功时,才执行后一条命令; ||
表示上一 条命令执行失败后,才执行下一条命令)
复制 [root@localhost script]# [ 1 -lt 2 ] && echo True || echo False
True
复制 [root@localhost script]# [ ] && echo True || echo False
False
流程控制
if判断
基本语法
注意: if后要有空格
复制 if [ 条件判断 ]
then
程序
else
程序
fi
复制 if [ 条件判断 ]
then
程序
elif [ 条件判断 ]
then
程序
else
程序
fi
使用实例
输入一个数字, 如果数字是1则输出"This is 1", 否则输出"This not 1"
复制 [root@localhost script]# cat ./script.sh
#!/bin/bash
if [ $1 = 1 ]
then
echo "This is 1"
else
echo "This not 1"
fi
[root@localhost script]# ./script.sh 1
This is 1
输入一个字符串, 若此字符串是"henry"则输出"This is henry", 否则输出"This not henry"
复制 [root@localhost script]# cat script.sh
#!/bin/bash
if [ "$1"x = "henry"x ]
then
echo "This is henry"
else
echo "This not henry"
fi
[root@localhost script]# ./script.sh henry
This is henry
在$1
后面拼接字符串'x'的目的是, 当$1
的值为空时,"x"就不等于"henryx", 则会输出"This is not henry", 而不会出现报错
case语句
基本语法
复制 case $var in
"值1" )
若变量值为 "值1" ,执行此程序
;;
"值2" )
若变量值为 "值2" ,执行此程序
;;
...
* )
若变量值都不是以上的值,执行此程序
;;
esac
最后的esac其实就是case反过来的形式, 代表case语句的结束
使用范例
输入一个数字, 若为1则输出"This is henry"; 若为"henry"则输出"This is henry"; 若上述都不是则输出"This is nothing"
复制 [root@localhost script]# cat script.sh
#!/bin/bash
case $1 in
1)
echo "This is 1"
;;
"henry")
echo "This is henry"
;;
*)
echo "This is nothing"
;;
esac
[root@localhost script]# ./script.sh 1
This is 1
[root@localhost script]# ./script.sh henry
This is henry
[root@localhost script]# ./script.sh what
This is nothing
for循环
基本语法
复制 for (( 初始值 ; 循环条件 ; 变量变化))
do
程序
done
复制 for var in value1 value2 value3
do
程序
done
使用实例
1.输入一个数字n, 输出从1加到n的总和
注意此处变量sum
赋值的时候不用添加$
, 但是引用的时候需要添加$
复制 [root@localhost script]# cat ./script.sh
#!/bin/bash
sum = 0
for (( i = 0 ; i <= $1 ; i ++ ))
do
sum = $ [ $sum + $i]
done
echo $sum
[root@localhost script]# ./script.sh 100
5050
2.打印所有输入的参数
复制 [root@localhost script]# cat script.sh
#!/bin/bash
sum = 0
for i in $1 $2 $3
do
echo $i
done
[root@localhost script]# ./script.sh henry tom terry
henry
tom
terry
while循环
基本语法
复制 while [ 条件判断式 ]
do
循环代码
done
使用实例
从1加到100(要注意赋值表达式之间没有空格)
复制 sum = 0
i = 1
while [ $i -le 100 ]
do
sum = $ [ $sum + $i]
i = $ [ $i +1 ]
done
echo $sum
read命令
基本语法
read
是一个用于从标准输入读取数据的命令, 可以通过键盘输入获取数据
命令语法格式如下, options
表示一些可选参数, variable
是一个或多个变量名,用于存储从标准输入读取的数据
复制 read [-options] [variable ...]
read命令的常用参数如下:
使用实例
在7秒内读取键盘输入的值并输出
复制 #!/bin/bash
read -p "在7秒内输入一个数字:" -t 7 input
echo $input
执行结果如下:
复制 [root@henry test]# ./test.sh
请输入一个数字:66
66
系统函数
basename
基本语法
basename
是一个在 Unix/Linux 系统中常用的命令,用于获取一个文件或路径的基本名称, 其语法格式如下:
复制 basename string [suffix]
其中,string
参数可以是一个文件名或路径,suffix
参数是一个可选的后缀,表示要删除的后缀部分
使用实例
复制 $ basename /usr/local/bin/python.exe
python.exe
$ basename /usr/local/bin/python.exe .exe
python
dirname
基本语法
dirname
命令用于从给定包含绝对路径的文件名去除文件名, 然后返回剩余的路径, 简单来说就是获取文件的所在目录
使用实例
复制 [root@henry test]# dirname /usr/bin/python.exe
/usr/bin
自定义函数
基本语法
若添加了return来获取函数返回值, 那么函数的返回值只能通过$?系统变量获取;若不添加return, 则以最后一条命令作为运行结果,return后跟数值
复制 function 函数名{
函数代码
return 返回值
}
使用实例
1.一个简单的加法函数, 有两种方法, 分别是使用return和不使用return
复制 #!/bin/bash
function sum () {
return $(($1 + $2))
}
echo "请输入两个值:"
read var1 var2
sum $var1 $var2
result = $?
echo $result
复制 #!/bin/bash
function sum () {
echo $(($1 + $2))
}
echo "请输入两个值:"
read var1 var2
result = $( sum $var1 $var2)
echo $result
2.通过遍历来获取指定格式文件的数量
复制 #!/bin/bash
# Define a custom function
function count_files {
local dir = $1 #使用local来定义局部bian'liang
local ext = $2
local count = 0
for file in "$dir" /*. "$ext" ; do
if [ -f "$file" ]; then
count = $(( count+1 ))
fi
done
echo "$count"
}
# Call the custom function
num_files = $( count_files /path/to/directory txt )
echo "There are $num_files text files in the directory."