您的当前位置:首页正文

linux中,如何写一个shell脚本

2024-11-08 来源:个人技术集锦

一、shell基础概念

shell是一个用C语言编写的程序,是使用linux的桥梁。shell其实可以是一种命令语言也可以是一种程序设计语言

1. shell脚本

也就是shell script,是一种为shell编写的脚本程序。很多人都会把shell script直接称为shell,这个时候我们心里要清楚其实对方要说的就是shell script;

2. shell环境

? 文本编辑器(编写脚本)+ 解释器(解释执行的脚本)
linux的shell种类很多,初学阶段就只用了解 Bourne Again Shell(/bin/bash),容易使用也免费是主流linux系统默认的shell。

3.如何编写一个shell脚本

在linux中,通过vi/vim编辑一个后缀名为xxx.sh的文件就可以了,扩展名其实并不影响脚本执行,只不过是为了后面自己活着是其他人看见这个文件名就知道这是一个shell脚本文件,省的需要cat来看这个是啥文件。
执行 vim test.sh命令,编写如下的内容

#!/bin/bash
echo "hello littlecat"
~     

shell脚本固定格式
开头第一行固定 #!/bin/bash
#!是一个约定的标记,告诉脚本指定的解释器是/bin/bash,使用#!/bin/bash,有一定的局限性,建议大家使用#!/usr/bin/env bash 可以缩写为#!/bin/env bash

#!/bin/env bash
#Description: shell描述信息
# Auth:脚本编写者
# Email:联系方式
# Data:编写日期
# Version:

4. 运行shell脚本

作为执行程序运行

[root@hcss-ecs-72ce paipai]# ./test.sh
-bash: ./test.sh: 权限不够
[root@hcss-ecs-72ce paipai]# ll -d ./test.sh
-rw-r--r-- 1 root root 35 716 10:41 ./test.sh
[root@hcss-ecs-72ce paipai]# #为脚本添加执行权限
[root@hcss-ecs-72ce paipai]# chmod +x ./test.sh
[root@hcss-ecs-72ce paipai]# ll -d ./test.sh
-rwxr-xr-x 1 root root 35 716 10:41 ./test.sh
[root@hcss-ecs-72ce paipai]# ./test.sh
hello littlecat
[root@hcss-ecs-72ce paipai]# 

作为解释器参数

直接运行解释器,把shell脚本文件名直接作为参数。如:

[root@hcss-ecs-72ce paipai]# /bin/bash ok.sh
paipai baby 

用这样的方式进行脚本编辑时,不用在脚本里注明约定的#!标记,而且即使这个脚本文件没有执行权限,也能出执行结果~

[root@hcss-ecs-72ce paipai]# vim ok.sh
[root@hcss-ecs-72ce paipai]# ll -d ./ok.sh 
-rw-r--r-- 1 root root 32 716 11:01 ./ok.sh
[root@hcss-ecs-72ce paipai]# /bin/bash ok.sh
paipai baby 
[root@hcss-ecs-72ce paipai]# ./ok.sh
-bash: ./ok.sh: 权限不够
[root@hcss-ecs-72ce paipai]# 

? 两种方式都可以执行脚本,各有利弊。

二、shell变量

1.定义变量

直接赋值
跟所有的编程语言一样,变量就是用来赋值的名称。变量赋值跟Java编程语言保持一致
变量名=“赋予的值”,为变量赋值时可以使用单引号也可以使用双引号

age="18"

⚠️ 变量名和等号之间不能有空格,变量名的命名需要遵守以下规则

  • 变量名可包含字母、数字、下划线_
  • 数字不能作为变量名的开头
  • 不能包含特殊字符(?!@ & *……)
  • 不能使用shell关键字(if、then、while、else、for……)作为变量名避免造成不必要的误会
  • 用全大写字母表示常量
  • 不能使用空格,空格通常是分割命令和参数的

2.使用变量

使用一个定义过的变量,只需要在变量前面加一个$
编写脚本: vi ok.sh

#!/bin/bash
cat_age="3"
name="paipai"
echo $cat_age
echo ${name}

第一种执行方式

[root@hcss-ecs-72ce paipai]# /bin/bash ok.sh 
3
[root@hcss-ecs-72ce paipai]# 

第二种执行方式

[root@hcss-ecs-72ce paipai]# ./ok.sh
-bash: ./ok.sh: 权限不够
[root@hcss-ecs-72ce paipai]# chmod +x ./ok.sh 
[root@hcss-ecs-72ce paipai]# ./ok.sh
3
[root@hcss-ecs-72ce paipai]# 

?:引用变量名的时候可以 ${变量名},花括号可加可不加,作用是为了帮助解释器识别变量边界,推荐给所有的编程变量引用加上花括号养成良好的编程习惯。

3. 只读变量(readonly)

使用readonly把变量设置为只读,且不可修改。即使重新为变量赋值,也不会成功,且会提示变量只可读。
脚本内容

#!/bin/bash
age="3"
readonly age
age="4"
echo ${age}

执行结果

[root@hcss-ecs-72ce paipai]# ./ok.sh 
./ok.sh:行4: age: 只读变量
3

4. 删除变量(unset)

删除语法:unset 变量名

脚本内容

#!/bin/bash
age="3"
unset age
echo ${age}

执行结果(没有任何输出)

[root@hcss-ecs-72ce paipai]# /bin/bash ok.sh

[root@hcss-ecs-72ce paipai]# ./ok.sh 

[root@hcss-ecs-72ce paipai]# 

5. 变量类型

shell支持的变量

变量类型说明
字符串变量在shell中,变量通常被视为字符串
整数变量可以使用declare或者是typeset来声明这是一个整数变量。当使用整数变量来进行声明时。如果后续尝试把非整数赋值给此变量。shell就会尝试将其转换为整数变量 例如typeset age=“15”
数组变量允许在一个变量中储存多个值
环境变量操作系统或者用户配置的用于配置shell的行为,影响其执行的环境;
特殊变量在shell中有特殊的执行意义 ;

⚠️ 重点需要关注的几个变量信息

  • 数组变量
age=(2 4 6 8 12)
  1. 关联数组 declare -A
    定义关联数组时,前面加参数-A,表示创建一个关联数组(也称为哈希表或者是字典)。-A参数告诉declare命令,紧随其后的变量是一个关联数组。
    (key1,value1) (key2,value2)……的键值对。
#!/bin/bash
declare -A student_array
#赋值
student_array["age"]="18"
student_array["like"]="Apple"
student_array["hair"]="black"
#访问数组元素
echo "${student_array["age"]}"

运行脚本得到结果

[root@hcss-ecs-72ce paipai]# ./ok.sh 
18
[root@hcss-ecs-72ce paipai]# 

⚠️:定义变量时的英文拼写一定要跟使用变量时的英文拼写保持一致,差一个英文字母,结果就会完全不一样。后续报错的时候也可以先往检查拼写是否正确的思路上走;

  • 环境变量
    操作系统或者是用户自己配置的影响环境的变量
    例如PATH变量就包含了操作系统可以执行的文件路径
[root@hcss-ecs-72ce paipai]# echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
[root@hcss-ecs-72ce paipai]# 
  • 特殊变量
$0 表示脚本名称
$1 $2…… 表示脚本的参数
$# 表示传递给脚本的参数数量

三、shell字符串(str)

字符串,shell编程中最常用的数据类型。字符串可以用单引号可以用双引号也可以不用。
但是单引号跟双引号在字符串拼接的时候,就会产生优劣对比。为了规范,后续字符串拼接一律使用双引号;

1.双引号

#!/bin/bash
cat_name="paipai"
str="hello,your cats name is ${cat_name}?"
echo -e $str

执行结果

[root@hcss-ecs-72ce paipai]# ./ok.sh 
hello,your cats name is paipai?
[root@hcss-ecs-72ce paipai]# 

双引号的优点
双引号可以直接引用变量
双引号可以出现转义字符

2.拼接字符串(使用双引号or单引号)

脚本内容

#!/bin/bash
cat_name="paipai"
#双引号进行拼接
str="hello,${cat_name}!"
#单引号进行拼接
str2='hello,my ${cat_name}!'

执行结果

[root@hcss-ecs-72ce paipai]# ./ok.sh 
hello,paipai! hello,my ${cat_name}!
[root@hcss-ecs-72ce paipai]# 

??‍♀️ 可以看到用单引号拼接出来的,没有成功引用变量。直到把花括号{}去掉;
哈哈哈哈 反复验证才发现不是花括号的问题,而是引号的问题,使用单引号进行拼接时。需要再拼接的变量外面再加个单引号。使用双引号进行拼接时,变量名称后面无需加双引号

#!/bin/bash
cat_name="paipai"
#双引号进行拼接
str="hello,${cat_name}!"
#单引号进行拼接
str2='hello,my '${cat_name}!''
echo $str 
echo $str2

执行结果

[root@hcss-ecs-72ce paipai]# ./ok.sh 
hello,paipai!
hello,my paipai!

3.获取字符串长度

获取对应字符创长度

#!/bin/bash
str="abcde"
echo ${#str};
echo ${#str[0]};

执行结果

[root@hcss-ecs-72ce paipai]# ./ok.sh 
5
5
[root@hcss-ecs-72ce paipai]# 

4.提取字符串

公式:str:n:m指定从第n个字符串开始,提取m个字符串。

#!/bin/bash
str=abcdefghijk
echo ${str:1:4} #会输出bcde
echo ${#str}

执行结果

[root@hcss-ecs-72ce paipai]# ./ok.sh 
bcde
11
[root@hcss-ecs-72ce paipai]# 

5. 查找子字符串

查找字符串中某个字符第一次出现的位置

#!/bin/bash
str="runoob is a great site"
echo `expr index "$str" r`
echo ${str:1:4}
echo  ${str:0:4}

执行结果

[root@hcss-ecs-72ce paipai]# ./ok.sh 
1
unoo
runo
[root@hcss-ecs-72ce paipai]#

?:提取字符串时,第一个字符的索引值为0;查找字符串时第一个字符是索引值为1
提取字符串(0,1,2,3,4……)
查找字符串(1,2,3,4……)

四、shell 数组

bash仅支持一维数组(不支持多维数组),且不限制一维数组的大小

1.定义数组

shell中用括号表示数组,数组元素用“空格”分割。
数组名=(value1 value2 ……value n)

  • 形式1
#!/bin/bash
array_name=(value0	value1	……valuen)
  • 形式2
#!/bin/bash
array_name=(
value0
value1
……
valuen
)
  • 形式3 单独定义数组各个分量;
#!/bin/bash
array_name[0]=value0
array_name[1]=value1
array_name[n]=valuen

2.读取数组

  • 读取数组元素格式
#!/bin/bash
array_name[0]=小一
array_name[1]=小二
array_name[6]=小6
echo ${array_name[1]}

执行结果

[root@hcss-ecs-72ce paipai]# ./ok.sh 
小二
[root@hcss-ecs-72ce paipai]#
  • 使用@符号可以把数组中所有的元素获取出来
#!/bin/bash
array_name[0]=小一
array_name[1]=小二
array_name[6]=小6
echo ${array_name[@]}

执行结果

[root@hcss-ecs-72ce paipai]# ./ok.sh 
小一 小二 小6
[root@hcss-ecs-72ce paipai]#

3.获取数组的长度

获取数组长度与获取字符串长度方法相同,

#!/bin/bash
array_name[0]=小一
array_name[1]=小二
array_name[6]=小6
array_name[9]=abcde
echo ${array_name[@]}
# 取得数组元素的个数语法1
echo ${#array_name[@]}
# 取得数组元素的个数语法2
echo ${#array_name[*]}
# 取得数组元素
echo ${#array_name[9]}

执行结果

[root@hcss-ecs-72ce paipai]# ./ok.sh 
小一 小二 小6 abcde
4
4
5
[root@hcss-ecs-72ce paipai]# 

五、shell注释

1、单行注释

以# 开头的行就是注释行,会被解释器忽略
通过每一行加一个#号设置多行注释

#--------------------------------------------
# 这是一个注释
# author:A超
# site:www.runoob.com
# slogan:学的安身立命
#--------------------------------------------
##### 用户配置区 开始 #####
#
#
# 加脚本描述信息
# 
#
##### 用户配置区 结束  #####

? 如果在开发过程中,遇到大段代码需要临时注释起来,可以把需要注释的代码用一对花括号括起来,定义成一个函数。无调用,不执行,达到和注释一样的效果

2. 多行注释

使用Here文档

#!/bin/bash
方式一
:<<EOF
XXX
XXXX
XXXX
EOF

方式二
: <<'COMMENT'
要注释的内容
可以有多行内容
COMMENT

方式三
:<<!
注释的内容
可以写很多行
注释的内容
!
显示全文