Shell 脚本的编写总结

简介: 这篇文章主要是为了记录一下Shell脚本的使用语法,前几天写了一个shell脚本,其中,也遇到了一些语法不清楚的情况,在此记录一下已备后续使用

1. 简介

这篇文章主要是为了记录一下Shell脚本的使用语法,前几天写了一个shell脚本,其中,也遇到了一些语法不清楚的情况,在此记录一下已备后续使用。

2. 什么是Shell脚本

Shell脚本(英语:Shell script)是一种电脑程序与文本文件,内容由一连串的shell命令组成,经由Unix Shell直译其内容后运作。被当成是一种脚本语言来设计,其运作方式与直译语言相当,由Uninx shell扮演命令行解释器的角色,在读取shell script之后,依次运行其中的shell命令,之后输出结果。利用Shell script可以进行系统管理、文件操作等。

2.1. 来个实例

创建一个名为demo1.sh的shell脚本文件,在该shell脚本中添加如下内容:

#!/bin/sh
cd ~
mkdir shell_tut
cd shell_tut
for((i=0;i<3;i++));do
  touch test_$i.txt
done

点击保存之后,在通过命令sh demo1.sh 来执行该脚本。即可达到我们预期的效果。

实例解析:


第1行:指定脚本解析器,这里是用/bin/sh 做解析器的。

第2行:切换到当前用户的home目录,因为我是用root用户登录的,所以我这边的用户目录是/root

第3行:创建一个目录shell_tut

第4行:切换到shell_tut目录

第5行:循环条件,一共循环10次

第6行:创建一个test_1....2.txt文件

第7行:循环体结束

cd, mkdir, touch都是系统自带的程序,一般在/bin或者/usr/bin目录下。for, do, done是sh脚本语言的关键字。

3. 环境

shell编程跟java、php编程一样,只要有一个能编写代码的文本编辑器和一个能解释执行的脚本解释器就可以了。当前主流的操作系统都支持shell编程,本文所述的shell编程是指Linux下的shell,讲的基本都是POSIX标准下的功能,所以,也适用于Unix及BSD(如Mac OS)。

系统 说明
Linux Linux默认安装就带了shell解释器。
Mac OS Mac OS 不仅带了sh、bash这两个最基础的解释器,还内置了ksh、csh、zsh等不常用的解释器
Windows windows出厂时没有内置shell解释器,需要自行安装,为了同时能用grep, awk, curl等工具,最好装一个cygwin或者mingw来模拟linux环境。

4.脚本解释器

4.1. sh

即Bourne shell,POSIX(Portable Operating System Interface)标准的shell解释器,它的二进制文件路径通常是/bin/sh,由Bell Labs开发。

4.2. bash

Bash是Bourne shell,属GNU Project,二进制文件路径通常是/bin/bash。业界通常混用bash、sh、和shell

5. 第一个shell脚本

5.1. 编写

打开文件编辑器,新建一个文件,扩展名为sh(sh代表shell),在脚本前面一般会加上#!/bin/bash 或者#!/bin/sh 用于指定解释器。

输入一些代码,第一行一般是这样的:

#!/bin/sh
#!/bin/bash

#!是一个约定的标记,它告诉系统这个脚本需要什么解释器来执行。

需要注意的是编码格式是需要是Unix(LF) 下的UTF-8格式。

5.2. 运行

运行Shell脚本有两种方法:

第一种方法,sh 【shell脚本名称】

sh demo1.sh

第二种方法./【shell脚本名称】

chmod +x demo1.sh
./demo1.sh

需要注意的是,一定要写成./demo1.sh,而不是demo1.sh,运行其他二进制的程序也一样,直接写demo1.sh,Linux系统会去PATH里寻找有没有叫demo1.sh的,而只有/bin,/sbin,/usr/bin,/usr/sbin等在PATH里。你的当前目录通常不在PATH里,所以写成demo1.sh是会找不到命令的,要用./demo1.sh告诉系统说,就在当前目录找。

6. shell变量

6.1.定义变量

定义变量时,变量名不加美元符合,如:

project_path=/data/server/demo_project

注意,变量名和等号之间不能有空格,变量的命令需要遵循如下原则:

命名只能使用英文字母,数字和下划线,首个字符不能以数字开头。

中间不能有空格,可以使用下划线_。

不能使用标点符号。

不能使用bash里的关键字

6.2. 使用变量

使用定义的变量,只需要在变量名前面加美元符号即可,如:

project_path=/data/server/demo_project
echo $project_path
echo ${project_path}

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

7. Shell 字符串

字符串是shell编程中最常用最有用的数据类型(除了数字和字符串,也没啥其它类型好用了),字符串可以用单引号,也可以用双引号,也可以不用引号。

7.1. 单引号

str='这是一个单纯的字符串'
echo $str

7.2. 双引号

name="码农飞哥"
echo "我的名字是${name}"

双引号与单引号的区别在于,双引号里面可以有变量,而单引号里面添加变量无效,它只会原样输出单引号里的内容。

7.3. 获取字符串长度

string="abcd"
echo ${#string}   # 输出 4

提取子字符串

以下实例从字符串第 2 个字符开始截取 4 个字符:

7.4. 定义数组

在 Shell 中,用括号来表示数组,数组元素用"空格"符号分割开。定义数组的一般形式为:数组名=(值1 值2 ... 值n)

例如:

array_name=(
 "张三",
"李四",
"王五",
)
echo ${array_name[1]}

8. 运算符

8.1. 算术运算符

原生bash不支持简单的数学运算,但是可以通过其他命令来实现,例如 awk和expr,expr最常用,expr是一款表达式计算工具,使用它能完成表达式的求值操作。

例如,两个树相加(注意使用的是反引号**`,而不是单引号’**)

例如:

#!/bin/bash
val=`expr 2 + 2`
echo "两数之和为 : $val"

执行脚本,输出结果是:两数之和为 : 4

PS:需要注意的是:

1.表达式和运算符之间要用空格,例如2+2是不对的,必须写成 2 + 2,
下表列出常用的算术运算符,假定变量a为10,变量b为10;

运算符 说明 举例
+ 加法 val=expr $a + $b 结果为30
- 减法 val=expr $a - $b 结果为0
* 乘法 expr $a \* $b 结果为 100
/ 除法 expr $b / $a 结果为 1
% 取余 expr $b % $a 结果为 0
= 赋值 a=$b 把变量 b 的值赋给 a
== 相等。用于比较两个数字,相同则返回 true。 [ $a == $b ] 返回 true
!= 不相等。用于比较两个数字,不相同则返回 true [ $a != $b ] 返回 false

注意:条件表达式要放在方括号之间,并且要有空格,例如: [a = = a==a==b] 是错误的,必须写成 [ $a == $b ]。

实例:

#!/bin/bash
#author:码农飞哥
#url:https://feige.blog.csdn.net/
a=10
b=10
val=`expr $a + $b`
echo "a + b : $val"
val=`expr $a - $b`
echo "a - b : $val"
val=`expr $a \* $b`
echo "a * b : $val"
val=`expr $b / $a`
echo "b / a : $val"
val=`expr $b % $a`
echo "b % a : $val"
if [ $a == $b ]
then
   echo "a 等于 b"
fi
if [ $a != $b ]
then
   echo "a 不等于 b"
fi

8.2 关系运算符

关系运算符只支持数字,不支持字符串,除非字符串的值是数字,下表 列出了常用的关系运算符,假定变量a为10,变量b为10

运算符 说明 举例
-eq 检测两个数是否相等,相等返回true [ $a -eq $b ] 返回 true
-ne 检测两个数是否不相等,不相等返回 true。 $a -eq $b ] 返回 false
-gt 检测左边的数是否大于右边的,如果是,则返回true [ $a -gt $b ] 返回 false
-lt 检测左边的数是否小于右边,如果是,则返回true [ $a -gt $b ] 返回 false
-ge 检测左边的数是否大于等于右边的,如果是,则返回 true。 [ $a -ge $b ] 返回 true
-le 检测左边的数是否小于等于右边的,如果是,则返回 true。 [ $a -le $b ] 返回 true
实例:


#!/bin/bash
#author:码农飞哥
#url:https://feige.blog.csdn.net/
a=10
b=10
if [ $a -eq $b ]
then
 echo "$a -eq $b":"a 等于 b"
else
 echo "$a -eq $b":"a 不等于 b"
fi
if [ $a -ne $b  ]
then
 echo "$a -ne $b: a 不等于b"
else
 echo "$a -ne $b a 等于 b"
fi
if [ $a -gt $b ]
then
 echo "$a -gt $b: a 大于 b"
else
 echo "$a -gt $b: a 不大于 b"
fi
if [ $a -lt $b ]
then
   echo "$a -lt $b: a 小于 b"
else
   echo "$a -lt $b: a 不小于 b"
fi
if [ $a -ge $b ]
then
   echo "$a -ge $b: a 大于或等于 b"
else
   echo "$a -ge $b: a 小于 b"
fi
if [ $a -le $b ]
then
   echo "$a -le $b: a 小于或等于 b"
else
   echo "$a -le $b: a 大于 b"
fi

8.3 逻辑运算符

假设变量a为10,变量b为15;

运算符 说明 举例
&& 逻辑的AND [[ $a -lt 100 && $b -gt 100 ]] 返回 false

实例:

a=10
b=15
if [[ $a -lt 100 && $b -gt 100 ]]
then
   echo "返回 true"
else
   echo "返回 false"
fi
if [[ $a -lt 100 || $b -gt 100 ]]
then
   echo "返回 true"
else
   echo "返回 false"
fi

8.4 字符串运算符

下表列出了常用的字符串运算符,假定变量a为"abc",变量b为"efg":

运算符 说明 举例
= 检测两个字符串是否相等,相等返回true [ $a = $b ] 返回 false
!= 检测两个字符串是否不相等,不相等返回 true [ $a != $b ] 返回 true
-z 检测字符串长度是否为0,为0返回 true [ -z $a ] 返回 false
-n 检测字符串长度是否不为 0,不为 0 返回 true。 [ -n “$a” ] 返回 true。
$ 检测字符串是否不为空,不为空返回 true。 [ $a ] 返回 true。
实例:


实例:  

a="abc"
b="efg"
if [ $a = $b ]
then
   echo "$a = $b : a 等于 b"
else
   echo "$a = $b: a 不等于 b"
fi
if [ $a != $b ]
then
   echo "$a != $b : a 不等于 b"
else
   echo "$a != $b: a 等于 b"
fi
if [ -z $a ]
then
   echo "-z $a : 字符串长度为 0"
else
   echo "-z $a : 字符串长度不为 0"
fi
if [ -n "$a" ]
then
   echo "-n $a : 字符串长度不为 0"
else
   echo "-n $a : 字符串长度为 0"
fi
if [ $a ]
then
   echo "$a : 字符串不为空"
else
   echo "$a : 字符串为空"
fi

8.5 文件测试运算符

文件测试运算符用于检测 Unix 文件的各种属性。这里指定file为 /data/server/xiang/script/testscript/demo.sh

操作符 说明 举例
-d file 检测文件是否是目录,如果是,则返回true [ -d $file ] 返回false
-f file 检测文件是否是普通文件(既不是目录,也不是设备文件),如果是,则返回true [ -f $file ] 返 true
-r file 检测文件是否可读,如果是,则返回true。 [ -r $file ] 返回 true
-w file 检测文件是否可写,如果是,则返回 true。 [ -w $file ] 返回 true。
-s file 检测文件是否为空(文件大小是否大于0),不为空返回 true。 [ -s $file ] 返回 true
-e file 检测文件(包括目录)是否存在,如果是,则返回 true。 [ -e $file ] 返回 true
实例:


#!/bin/bash
file="/data/server/xiang/script/testscript/demo.sh"
ile="/var/www/runoob/test.sh"
if [ -r $file ]
then
   echo "文件可读"
else
   echo "文件不可读"
fi
if [ -w $file ]
then
   echo "文件可写"
else
   echo "文件不可写"
fi
if [ -f $file ]
then
   echo "文件为普通文件"
else
   echo "文件为特殊文件"
fi
if [ -d $file ]
then
   echo "文件是个目录"
else
   echo "文件不是个目录"
fi
if [ -s $file ]
then
   echo "文件不为空"
else
   echo "文件为空"
fi
if [ -e $file ]
then
   echo "文件存在"
else
   echo "文件不存在"
fi

9. shell echo命令

9.1. 显示普通字符

echo "这是一个普通字符"

9.2. 显示转义字符

echo "\"这是一个转义字符 \""

9.3. 显示变量

name="张三三"
echo "我的名字是${name}"

9.4. 显示结果定向至文件

echo "我是一个测试文本">myfile

10. Shell流程控制

10.1 if fi

if 语句语法格式:

if condition
then
  command1
  ....
  commandN
fi

写成一行

if [ $(ps -ef|grep -c "nginx") -gt 1 ];then echo "true";fi

10.2 if else fi

if else fi 语法格式:

if condition
then
    command1 
    command2
    ...
    commandN
else
    command
fi

实例:

a=10
b=10
if [ $a -eq $b ]
then
 echo "$a -eq $b":"a 等于 b"
else
 echo "$a -eq $b":"a 不等于 b"
fi

10.3 if elif fi

if elif fi的语法结构是:

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

11. for 循环

Shell支持for循环

for循环一般格式为:

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

写成一行

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

当变量值在列表里,for循环即执行一次所有命令,使用变量名获取列表中的当前取值。命令可为任何有效的shell命令和语句。in列表可以包含替换、字符串和文件名。

in列表示可选的,如果不用它,for循环使用命令行的位置参数。

for str in 我是 码农飞哥, 做一个 堂堂正正的中国人
do
   echo $str
done     

通过空格区分每一个item。

12. while循环

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

while condition
do
   command
done

如果a小于等于6,a从1开始,每次循环都对a加1,运行上述脚本,返回数字1到6,然后终止。

a=1
while (( $a<=6 ))
do
  echo $a
  let "a++"
done

这里的判断条件需要用(()),运行脚本,输出:

break 命令

break 命令允许跳出所有循环(终止执行后面的所有循环)。

13. 获取服务器IP地址

如果通过shell命令获取服务器的IP地址呢?

我们都知道通过 ifconfig 来获取服务器的网络配置情况,但是当有多个网卡的情况下,如果获取某个网卡的IP地址呢?如下图所示:如何获取网卡eth0的IP地址呢?

命令有点点小复杂,如下所示:

current_ip=$(ifconfig eth0|grep inet|grep -v inet6|awk '{print $2}')

命令解释:

ifconfig eth0 用于查询eth0网卡

grep inet 用于模糊查询inet开头的网络地址

grep -v inet6 用于剔除掉inet6

awk '{print $2}' 用于打印第二个参数。

14. 交互式的命令

shell同样支持交互式命令,shell脚本可以接收我们控制台输入的文本。

echo -n "input {文件名} :"
read
echo "输入的文件名是:$REPLY"

15. 查看文件中是否存在某内容

查找文件中是否存在某内容,可以通过cat 命令进行查找,其中/dev/null 通常被用于丢弃不需要的输出流,或作为用于输入流的空文件,这些操作通常由重定向完成,任何你想丢弃的数据都可以写入其中

丢弃标准输出

在写shell脚本的时候,只想通过命令的结果执行后面的逻辑,而不想命令执行过程中有一大堆中间结果输出,这时候可以把命令执行过程中的输入全部写入 /dev/null

if cat name.txt|grep 李三三 >/dev/null
then
  echo "文本已经存在不再添加"
else
  echo "文本不存在进行添加"
sed -i '$a\李三三' name.txt
fi

16. 对jar包进行解压&压缩

jar包是Java中一种可以直接运行的程序包,如果我们需要修改jar包中的某个文件的话,可以执行先执行解压命令

16.1 jar包解压

jar -xvf [jar包名称] [需要解压的文件的在jar中的相对路径]

比如需要修改app.jar包中的 application.yml 文件

jar -xvf  app.jar BOOT-INF/classes/application-prod.yml

这里的BOOT-INF/classes/application-prod.yml 是application.yml 文件在jar包中路径,注意不要写成绝对路径

16.2 将修改后的文件压缩进jar包中

可以通过sed命令对application.yml 进行修改,然后通过jar命令将修改后的application.yml 文件打进压缩包中

jar -ufjar包名称] [需要打进压缩包中的文件]

还是以上面的app.jar包为例

jar -uf  app.jar BOOT-INF/classes/application-prod.yml

17. 判断文件或者目录是否存在

判断文件或者目录是否存在,不存在则创建,比如首先判断/data/server/train 目录是否存在,不存在则创建

if [ -e /data/server/train ];then
  echo '目录已经存在'
else
  echo '目录不存在'
  mkdir -p /data/server/train
fi

18. war包的解压与压缩

18.1 解压war包

unzip train.war -d train

将train.war的内容解压到train目录中

18.2 压缩war包

压缩war包需要注意的是需要进入到目标目录的里面,然后对里面的文件进行压缩,不要在目标目录压缩,不然在war中就会多一层目录。

cd train
jar -cvf coep-train.war *

总结

本文详细介绍了Shell脚本的一些基础命令,下文将主要介绍sed命令



相关文章
|
26天前
|
Shell
一个用于添加/删除定时任务的shell脚本
一个用于添加/删除定时任务的shell脚本
68 1
|
12天前
|
Shell Linux 测试技术
6种方法打造出色的Shell脚本
6种方法打造出色的Shell脚本
36 2
6种方法打造出色的Shell脚本
|
3天前
|
Ubuntu Shell 开发工具
ubuntu/debian shell 脚本自动配置 gitea git 仓库
这是一个自动配置 Gitea Git 仓库的 Shell 脚本,支持 Ubuntu 20+ 和 Debian 12+ 系统。脚本会创建必要的目录、下载并安装 Gitea,创建 Gitea 用户和服务,确保 Gitea 在系统启动时自动运行。用户可以选择从官方或小绿叶技术博客下载安装包。
13 2
|
17天前
|
监控 网络协议 Shell
ip和ip网段攻击拦截系统-绿叶结界防火墙系统shell脚本
这是一个名为“小绿叶技术博客扫段攻击拦截系统”的Bash脚本,用于监控和拦截TCP攻击。通过抓取网络数据包监控可疑IP,并利用iptables和firewalld防火墙规则对这些IP进行拦截。同时,该系统能够查询数据库中的白名单,确保合法IP不受影响。此外,它还具备日志记录功能,以便于后续分析和审计。
40 6
|
14天前
|
运维 监控 Shell
深入理解Linux系统下的Shell脚本编程
【10月更文挑战第24天】本文将深入浅出地介绍Linux系统中Shell脚本的基础知识和实用技巧,帮助读者从零开始学习编写Shell脚本。通过本文的学习,你将能够掌握Shell脚本的基本语法、变量使用、流程控制以及函数定义等核心概念,并学会如何将这些知识应用于实际问题解决中。文章还将展示几个实用的Shell脚本例子,以加深对知识点的理解和应用。无论你是运维人员还是软件开发者,这篇文章都将为你提供强大的Linux自动化工具。
|
1月前
|
监控 Unix Shell
shell脚本编程学习
【10月更文挑战第1天】shell脚本编程
62 12
|
1月前
|
存储 运维 监控
自动化运维:使用Shell脚本简化日常任务
【9月更文挑战第35天】在IT运维的日常工作中,重复性的任务往往消耗大量的时间。本文将介绍如何通过编写简单的Shell脚本来自动化这些日常任务,从而提升效率。我们将一起探索Shell脚本的基础语法,并通过实际案例展示如何应用这些知识来创建有用的自动化工具。无论你是新手还是有一定经验的运维人员,这篇文章都会为你提供新的视角和技巧,让你的工作更加轻松。
43 2
|
2月前
|
Shell
shell脚本变量 $name ${name}啥区别
shell脚本变量 $name ${name}啥区别
|
2月前
|
人工智能 监控 Shell
常用的 55 个 Linux Shell 脚本(包括基础案例、文件操作、实用工具、图形化、sed、gawk)
这篇文章提供了55个常用的Linux Shell脚本实例,涵盖基础案例、文件操作、实用工具、图形化界面及sed、gawk的使用。
338 2
|
2月前
|
Shell
Shell脚本有哪些基本语法?
【9月更文挑战第4天】
63 18