文章目录

什么是 Shell

Shell 是一个用 C 语言编写的程序,它是用户使用 Linux 的桥梁。Shell 既是一种命令语言,又是一种程序设计语言。

Shell 脚本

Shell 脚本(shell script),是一种为 shell 编写的脚本程序。

Shell 环境

Shell 编程跟 JavaScript、php 编程一样,只要有一个能编写代码的文本编辑器和一个能解释执行的脚本解释器就可以了。

Shell 语法

打开文本编辑器(可以使用 vi/vim 命令来创建文件),新建一个文件 test.sh,扩展名为 sh(sh代表shell),扩展名并不影响脚本执行,见名知意就好,如果你用 php 写 shell 脚本,扩展名就用 php 好了。

授于执行权限

chmod +x ./test.sh  #使脚本具有执行权限
./test.sh #执行脚本

日志输出echo

echo "Hello World !"

变量

定义变量时,变量名和等号之间不能有空格,这可能和你熟悉的所有编程语言都不一样。同时,变量名的命名须遵循如下规则:

  • 命名只能使用英文字母,数字和下划线,首个字符不能以数字开头。
  • 中间不能有空格,可以使用下划线 _。
  • 不能使用标点符号。
  • 不能使用bash里的关键字(可用help命令查看保留关键字)。

示例:

your_name="runoob.com"

变量引用

your_name="qinjx"
echo $your_name
echo ${your_name}

变量名外面的花括号是可选的,加不加都行,加花括号是为了帮助解释器识别变量的边界,比如下面这种情况:

your_name="qinjx"
echo $your_name
echo ${your_name}hello

只读变量

使用 readonly 命令可以将变量定义为只读变量,只读变量的值不能被改变。

下面的例子尝试更改只读变量,结果报错:

myUrl="https://www.google.com"
readonly myUrl
myUrl="https://www.runoob.com"

运行脚本,结果如下:


/bin/sh: NAME: This variable is read only.


字符串

字符串可以用单引号,也可以用双引号,也可以不用引号。

  • 单引号里的任何字符都会原样输出,单引号字符串中的变量是无效的;
  • 单引号字串中不能出现单独一个的单引号(对单引号使用转义符后也不行),但可成对出现,作为字符串拼接使用。

双引号的优点:

  • 双引号里可以有变量
  • 双引号里可以出现转义字符

if else

if 语句语法格式:

if condition
then
command1
command2
...
commandN
fi

举例:

a=10
b=10
if [ $a == $b ]
then
echo "a 等于 b"
elif [ $a -gt $b ]; then
echo "a 大于 b"
elif [ $a -lt $b ]; then
echo "a 小于 b"
else
echo "没有符合的条件"
fi

for循环

for循环一般格式为:

for var in item1 item2 ... itemN
do
command1
command2
...
commandN
done

写成一行:

for var in item1 item2 ... itemN; do command1; command2… done;

举例:

for i in {1..5} ; do
echo "遍历 $i"
done

输出:

遍历 1
遍历 2
遍历 3
遍历 4
遍历 5

举例:

for str in Hello new world
do
echo "遍历 $str"
done

输出:

遍历 Hello
遍历 new
遍历 world

while 语句

while 循环用于不断执行一系列命令,也用于从输入文件中读取数据。其语法格式为:

while condition
do
command
done

举例:

int=1
while(( $int<=5 ))
do
echo $int
let "int++"
done

运行脚本,输出:

1
2
3
4
5

以上实例使用了 Bash let 命令,它用于执行一个或多个表达式,变量计算中不需要加上 $ 来表示变量.

举例:

num=18
while [ $num -le 100 ] #-le 小于或者等于
do
let num++
echo "while $num"
done

case … esac

case … esac 为多选择语句,与其他语言中的 switch … case 语句类似,是一种多分支选择结构,每个 case 分支用右圆括号开始,用两个分号 ;; 表示 break,即执行结束,跳出整个 case … esac 语句,esac(就是 case 反过来)作为结束标记。

case … esac 语法格式如下:

case  in
模式1)
command1
command2
...
commandN
;;
模式2)
command1
command2
...
commandN
;;
esac

case 工作方式如上所示,取值后面必须为单词 in,每一模式必须以右括号结束。取值可以为变量或常数,匹配发现取值符合某一模式后,其间所有命令开始执行直至 ;;。

取值将检测匹配的每一个模式。一旦模式匹配,则执行完匹配模式相应命令后不再继续其他模式。如果无一匹配模式,使用星号 * 捕获该值,再执行后面的命令。

举例:

echo '输入 1 到 4 之间的数字:'
echo '你输入的数字为:'
read aNum
case $aNum in
1) echo '你选择了 1'
;;
2) echo '你选择了 2'
;;
3) echo '你选择了 3'
;;
4) echo '你选择了 4'
;;
*) echo '你没有输入 1 到 4 之间的数字'
;;
esac

字符串匹配

site="runoob"

case "$site" in
"runoob") echo "菜鸟教程"
;;
"google") echo "Google 搜索"
;;
"taobao") echo "淘宝网"
;;
esac

输出结果为:


菜鸟教程


数组

例子1:

name=(zhao zhang li)
echo "元素:${name[1]}"
echo "所有元素:${name[*]}"
echo "数组长度:${#name[*]}"
echo "数组长度:${#name[@]}"

例子2:

#单独给某个元素复制
name[1]=wang

函数

shell中函数的定义格式如下:

[ function ] funname [()]

{

action;

[return int;]

}

说明:

  • 1、可以带function fun() 定义,也可以直接fun() 定义,不带任何参数。
  • 2、参数返回,可以显示加:return 返回,如果不加,将以最后一条命令运行结果,作为返回值。 return后跟数值n(0-255)

举例

demoFun(){
echo "这是我的第一个 shell 函数!"
}
echo "-----函数开始执行-----"
demoFun
echo "-----函数执行完毕-----"

输出结果:

-----函数开始执行-----
这是我的第一个 shell 函数!
-----函数执行完毕-----

下面定义一个带有return语句的函数:

function sum() {
a=10
b=20
return $((a+b))
}

echo '开始执行函数'
sum
#接收函数返回值
echo "result: $?"

输出结果:

开始执行函数
result: 30

​函数返回值在调用该函数后通过 $? 来获得。​

注意:所有函数在使用前必须定义。这意味着必须将函数放在脚本开始部分,直至shell解释器首次发现它时,才可以使用。调用函数仅使用其函数名即可。

函数传参

在Shell中,调用函数时可以向其传递参数。在函数体内部,通过 $n 的形式来获取参数的值,例如,$1表示第一个参数,$2表示第二个参数…

带参数的函数示例:

function sum() {
# $1表示第一个参数,$2表示第二个参数.
a=$1
b=$2
return $((a+b))
}

echo '开始执行函数'
sum 2 3
#接收函数返回值
echo "result: $?"

输出:

开始执行函数
result: 5

举例:

funWithParam(){
echo "第一个参数为 $1 !"
echo "第二个参数为 $2 !"
echo "第十个参数为 $10 !"
echo "第十个参数为 ${10} !"
echo "第十一个参数为 ${11} !"
echo "参数总数有 $# 个!"
echo "作为一个字符串输出所有参数 $* !"
}
funWithParam 1 2 3 4 5 6 7 8 9 34 73

输出结果:

第一个参数为 1 !
第二个参数为 2 !
第十个参数为 10 !
第十个参数为 34 !
第十一个参数为 73 !
参数总数有 11 !
作为一个字符串输出所有参数 1 2 3 4 5 6 7 8 9 34 73 !

注意, 10 不 能 获 取 第 十 个 参 数 , 获 取 第 十 个 参 数 需 要 10 不能获取第十个参数,获取第十个参数需要 10不能获取第十个参数,获取第十个参数需要{10}。当n>=10时,需要使用${n}来获取参数。

另外,还有几个特殊字符用来处理参数:

  • $* :以一个单字符串显示所有向脚本传递的参数
  • @ : 与 @ :与 @:与*相同,但是使用时加引号,并在引号中返回每个参数。

外部文件引用

和其他语言一样,Shell 也可以包含外部脚本。这样可以很方便的封装一些公用的代码作为一个独立的文件。

Shell 文件包含的语法格式如下:

. filename   # 注意点号(.)和文件名中间有一空格



source filename

此方法,可以把很多工具类封装起来

首先定义一个工具类 ​​util.sh​​:

url="baidu.com"

function sum() {
# $1表示第一个参数,$2表示第二个参数.
echo "所有参数:$* "
a=$1
b=$2
return $((a+b))
}

​test.sh​

#外部文件引用
. util.sh

echo "变量引用:$url"

echo '开始执行函数'
#sum 函数在util.sh中
sum 2 3
#接收函数返回值
echo "result: $?"

判断字符串是否为空

str="abc"

if [ -z $str ]; then
echo "字符串为空"
else
echo "字符串不为空"
fi

test 命令

Shell中的 test 命令用于检查某个条件是否成立,它可以进行数值、字符和文件三个方面的测试。

  • 数值测试

-eq :等于则为真

-ne :不等于则为真

-gt :大于则为真

-ge :大于等于则为真

-lt :小于则为真

-le :小于等于则为真

举例:

num1=100
num2=100
if test $[num1] -eq $[num2]
then
echo '两个数相等!'
else
echo '两个数不相等!'
fi

输出结果:

两个数相等!
  • 基本运算

代码中的 [] 执行基本的算数运算,如:

a=5
b=6

result=$[a+b] # 注意等号两边不能有空格
echo "result 为: $result"

结果为:

result 为: 11
  • 字符串测试

= 等于则为真

!= 不相等则为真

-z 字符串 字符串的长度为零则为真

-n 字符串 字符串的长度不为零则为真

实例

num1="ru1noob"
num2="runoob"
if test $num1 = $num2
then
echo '两个字符串相等!'
else
echo '两个字符串不相等!'
fi

输出结果:


两个字符串不相等!


  • 文件测试

Shell脚本学习笔记_shell

举例:

if test -e ./bash
then
echo '文件已存在!'
else
echo '文件不存在!'
fi

输出结果:

文件已存在!

另外,Shell 还提供了与( -a )、或( -o )、非( ! )三个逻辑操作符用于将测试条件连接起来,其优先级为: ! 最高, -a 次之, -o 最低。例如:

if test -e ./notFile -o -e ./bash
then
echo '至少有一个文件存在!'
else
echo '两个文件都不存在'
fi

输出结果:

至少有一个文件存在!

实战一:遍历文件夹

#定义目录,遍历当前目录
fileDir="./*"

#遍历目录
for file in $fileDir ; do
echo "遍历:$file"
done

输出:

遍历:./main
遍历:./test
遍历:./test.sh
遍历:./util.sh

输出目录里的文件、文件夹

#定义目录
fileDir="./*"

#遍历目录
for file in $fileDir; do

if test -f "$file"; then
echo "遍历:$file 是文件"
elif test -d "$file"; then
echo "遍历:$file 是目录"
fi
done

实战二:深度遍历文件夹

#文件夹目录
fileDir="../assets"

function allFile() {
#接收参数
dir=$1

#遍历目录
for file in ${dir}/*; do

if test -f "$file"; then
echo "$file 是文件"
elif test -d "$file"; then
echo "$file 是目录"
allFile "$file"
fi

done
}

echo "开始执行遍历目录"
allFile $fileDir

输出结果:

Shell脚本学习笔记_shell_02