万字长文带你入门shell编程(超详细)

news2024/11/15 18:00:48

一、概述

Shell 是计算机操作系统中用户与操作系统内核之间的接口层,它提供了一种方式让用户能够通过命令行界面(CLI)与操作系统交互。Shell 可以被视为一个命令解释器,它接收用户输入的命令,解析这些命令,并将它们传递给操作系统以便执行。Shell 也会显示命令的执行结果,以及提供一系列的脚本语言功能,如变量、循环、条件判断和函数,使得用户能够编写脚本来自动化任务。

Shell脚本运行过程:

常见的 Shell 命令解释器:

  1. Bourne Shell (sh):UNIX 系统中最古老的 shell,是许多其他 shell 的基础。

  2. C Shell (csh):由贝尔实验室开发,提供了更类似于 C 语言的语法结构。

  3. Korn Shell (ksh):结合了 Bourne Shell 和 C Shell 的特性,提供了更多的功能和改进。

  4. Bash Shell (bash):GNU 项目的一部分,是 Linux 和 macOS 中最常用的 shell,提供了丰富的功能和广泛的脚本支持。

  5. Z Shell (zsh):一个高度可配置的 shell,提供了许多高级功能,如自动补全和语法高亮。

  6. PowerShell:Microsoft 开发的 shell 和脚本语言,主要用于 Windows 系统,也支持 Linux 和 macOS。

查看自己linux系统的默认解析:echo $SHELL

二、Shell脚本编写规范


首行设置Shell解释器类型,语法如下:

#!/bin/bash



单行注释:

#注释内容


多行注释:

:<<!

#注释内容1

#注释内容2

!

Shell脚本编写Hello World案例

 helloworld.sh文件内容(注意文件以.sh结尾)

脚本文件执行 

 

 注意:

当我执行  ./helloworld.sh的时候,报错了,第一次报错是因为权限不足,这时候修改一下文件权限就行;第二次报错/bin/bash/: bad interpreter: Not a directory。这个错误表明脚本的第一行(称为 shebang 行)指向的解释器路径有问题。在文件的开头我编写的是#!/bin/bash/,这里编写错了,正确的应该是#!/bin/bash

三、环境变量

有Linux基础的同学都知道当我们在shell终端执行cd命令的时候,实际上执行的就是/usr/bin/cd这个程序文件,那么我们是否会有这样的疑问,为何我们无论在哪个目录下都能执行cd命令?这其实就是环境变量的作用;我们可以执行env来查看当前的系统环境变量:

Linux知识回顾:

如果想输出特定的环境变量,可以执行echo $环境变量名:

设置临时环境变量export  变量名=变量值:

永久生效:

定义与使用

1.局部变量

在一个shell脚本文件中定义的变量只能给当前的脚本文件使用,这个变量就叫局部变量

定义语法:

var_name=name

语法规则:
1.变量名称可以有字母,数字和下划线组成,但是不能以数字开头
2.等号两侧不能有空格
3.在bash环境中,变量的默认类型都是字符串类型,无法直接进行数值运算4.变量的值如果有空格,必须使用双引号括起来
5.不能使用shell的关键字作为变量名称

下面展示变量的定义与访问:

2.常量

定义之后就不能修改

语法readonly 变量名

 3.全局变量

 在A.sh脚本中定义的变量能被B.sh脚本所访问

语法 export 变量名

demo1.sh:
#!/bin/bash
var_env="张三"
export var_env
sh demo2.sh



demo2.sh
#!/bin/bash
echo "输出环境变量var_env,值为${var_env}"



在终端执行sh demo1.sh

总结:

局部变量定义:变量名=变量值

常量定义:readonly 变量名

全局变量定义:export 变量名

查询变量:$变量名 、${变量名}

删除变量:unset 变量名

4.特殊变量

Shell 提供了一些预定义的特殊变量,如:

  • $0:脚本的名称。
  • $1$2, ...:脚本的参数。
  • $#:脚本参数的数量。
  • $?:最后执行的命令的退出状态。
  • $!:最后创建的后台进程的进程ID。

使用示例:

创建demo3.sh文件,文件内容如下:

#!/bin/bash
echo "输出脚本名称: $0"
echo "输出脚本第一个参数: $1"
echo "输出脚本第二个参数: $2"
echo "输出脚本第三个参数: $3"

echo "当参数超过十个的时候,10以后的参数要用花括号括起来,包括第十个: ${10}"

# 添加后台运行的命令
sleep 10 &

echo "最后执行命令的退出状态: $?"
echo "最后创建的后台进程的进程ID: $!"

四、字符串

常见字符串格式

1.单引号

任何字符串都会原样输出,在字符串中拼接变量是无效的

2.双引号

其中包含了变量,那么该变量会被解析得到的值,而不会原样输出

字符串中还可以出现双引号的子字符串,但需要转意

3.不被引号包围的字符串

不被引号包围的字符串中出现变量也会被解析,这一点和双引号" "包围的字符串一样

字符串中不能出现空格,否则空格后面的内容会被当做其他命令解析

4.获取字符串长度

语法:${#变量名}

字符串拼接

1.无符号拼接

2.双引号拼接

3.混合拼接

 字符串截取

语法:

注:字符串下标从0开始

五、数组

数组的定义

语法:

arr1=(item1 item2 item3)   #方式一,中间以空格隔开

arr2=([索引1]=item1 [索引2]=item2)  #方式二,自定义索引, = 两边不能有空格

数组的获取

1.通过下标获取数组元素,index从0开始

${arr[index]}

2.获取值的同时赋值给其他变量

item=${arr[index]}

3.使用@或*可以获取数组中的所有元素

${arr[@]}
${arr[*]}

4.获取数组长度

${#arr[@]}
${#arr[*]}

5.获取数组指定元素的字符串长度

${#arr[index]}

数组的拼接

数组的删除

1.删除数组中指定的元素

unset arr[index]

2.删除数组所有元素

unset arr

六、内置命令

Shell 内置命令,就是由 Bash shel 自身提供的命令,而不是文件系统中的可执行脚本文件。
使用type 来确定一个命令是否是内置命令:

type 命令

alias设置别名

当某些内置命令过长,而且又经常使用的时候,我们就可以通过设置别名的形式,把复杂的命令设置成简短的命令,语法如下

alias 别名='命令'

在终端运行alias时,可以查看当前的别名列表:

例如我们给ps -aux设置一个别名:

删除某个别名,语法如下:

unalias 别名

删除当前环境下的所有别名,语法如下:

unalias -a

read读取控制台输入

read命令的作用

read 是 Shell 内置命令,用于从标准输入中读取数据并赋值给变量。如果没有进行重定向,默认就是从终端控制台读取用户输入的数据;如果进行了重定向,那么可以从文件中读取数据。

read的语法如下:

read [-options] [var1 var2...]

options表示选项,如下表所示;var表示用来存储数据的变量,可以有一个也可以有多个。

options和var都是可选的,如果没有提供变量名,那么读取的数据将存到环境变量REPLY中。

$REPLY保存read最后一个读入命令的数据

options支持的参数:

使用read给多个变量赋值

创建一个read1.sh文件,内容如下:

#!/bin/bash
#使用read命令读取数据,要有提示信息“请输入姓名、年龄、爱好”,并且将数据赋值给多个变量
read -p "请输入姓名、年龄、爱好:" name age hobby
echo "姓名${name}"
echo "年龄${age}"
echo "爱好${hobby}"

使用read读取一个字符

创建一个read2.sh文件,内容如下:

#!/bin/bash
#使用read命令读取数据,要有提示信息“您确定要删除这条信息吗?请输入(y/n)”
read -n 1 -p "您确定要删除这条信息吗?请输入(y/n)" char
echo "所输入字符为${char}"

使用read限制时间输入

创建一个read3.sh文件,内容如下:

#!/bin/bash
#使用read命令读取数据,要有提示信息"请输入密码(20秒内):",并且设置限制时间20秒
read -t 20 -sp "请输入密码(20秒内):" pwd1
#输出一个换行
echo
#使用read命令读取数据,要有提示信息"请再次输入密码(20秒内):",并且设置限制时间20秒
read -t 20 -sp "请输入密码(20秒内):" pwd2
#输出一个换行
printf "\n"
#校验两次密码是否一致
if [$pwd1==$pwd2]
then
        echo "两次密码一致,验证通过"
else
        echo "两次密码不一致,验证失败"
fi

exit退出

在 Shell 脚本中,exit 命令用于立即终止脚本的执行。当 exit 命令被执行时,脚本会停止执行后续命令,并返回一个状态值给调用环境(如父 shell 或操作系统)。这个状态值通常用于指示脚本的退出状态或执行结果

exit 命令的基本语法如下:

exit [n]
  • 如果没有参数,exit 将返回状态值 0,这通常表示成功。
  • 如果提供了参数 nexit 将返回状态值 n。这个值通常是一个介于 1 到 255 之间的整数,用来表示脚本执行失败或异常的情况。

获取脚本状态码:

echo $?

返回非零状态值的意义

在脚本中返回非零状态值是一个重要的最佳实践,特别是当脚本作为更大工作流的一部分时。这允许调用脚本的程序或 shell 能够根据脚本的返回值采取不同的行动,如重新尝试、记录错误或执行清理操作。

示例:编写shell脚本使用exit 退出,退出时返回一个非0数字状态值,执行脚本文件并打印返回状态值:

#!/bin/bash

echo hello
exit 2

declare设置变量属性

declare命令用于声明 shell 变量。可用来声明变量并设置变量的属性,也可用来显示shell函数。若不加上任何参数,则会显示全部的shell变量与函数(与执行set指令的效果相同)。

1.设置变量属性

语法:

declare [+/-][frxiaA][变量名称=设置值]
参数说明
+/-"-“可用来指定变量的属性,”+"则是取消变量所设的属性。
-f仅用显示函数
-r变量设置成只读
-x指定变量为环境变量,可以为shell以外的程序来使用
-i[设置值]可以是数值,字符串或运算式。
-a设置为数组
-A设置为关联数组(有点像java中的map)
# 声明一个变量a 为正数变量 
declare -i a
a=12 #如果a="aa" 那么打印出来时0

#上面也可以简写为
declare -i a=12

# 如果非要将a进行赋值为"aa"
declare +i a
a="aa" #这样打印出的aa

#也可以设置只读
declare -r a

2.声明关联数组和普通索引数组

新版的bash shell 支持关联数组,关联数组使用字符串作为下标,而不是数字,这样方便我们知道某些内容具体代表什么意义。

关联数组是key-value键值对,有点像是java中的map。

#声明关系数组
declare -A cd
cd["name"]="zhangsan"
cd["age"]=12


#声明索引数组
declare -a cd='([0]="a" [1]="b" [2]="c")' //声明数组变量

let命令

let 是 Bash shell 中的一个内置命令,用于执行算术运算。它主要用于简单的整数运算,如加、减、乘、除以及位运算等。let 命令可以简化在 shell 脚本中进行算术计算的过程,尤其当涉及到变量赋值和表达式计算时。

基本语法

let 的基本语法如下:

let "expression"

或者,

let expression

在第二种形式中,letexpression 之间没有引号,这是因为在 let 内部不需要使用引号来包裹表达式。

示例

让我们看一些 let 命令的使用示例:

简单的算术运算

#!/bin/bash
a=5
b=3
let "c=a+b"
echo $c

这段脚本将输出 8

变量赋值

let 也可以直接用于变量赋值:

#!/bin/bash
let "result=5+3"
echo $result

这将输出 8

位运算

let 还支持位运算:

#!/bin/bash
let "x=5 & 3"
echo $x

这将输出 1,因为 53 在二进制下分别是 101011,按位与的结果是 001

自增和自减

let 也支持自增和自减操作:

#!/bin/bash
let "counter=0"
let "counter++"
echo $counter

这将输出 1

注意事项

  • let 默认执行整数运算,不支持浮点数。
  • 当使用 let 进行赋值时,无需在变量名前添加 $ 符号。
  • let 命令的输出不会自动打印,如果需要输出结果,需要通过 echo 或其他命令显示地输出。

七、运算符

shell支持多种运算符,包括:

  • 算数运算符
  • 关系运算符
  • 布尔运算符
  • 字符串运算符
  • 文件测试运算符

原生bash不支持简单的数学运算,但是可以通过其他命令来实现,例如 awk 和 expr,expr 最常用。

算术运算符

下表列出了常用的算术运算符,假定变量 a 为 10,变量 b 为 20:

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

注意

  • 条件表达式要放在方括号之间,并且要有空格,例如: [$a==$b] 是错误的,必须写成 [ $a == $b ]。 
  • 乘号(*)前边必须加反斜杠(\)才能实现乘法运算;
  • 在 MAC 中 shell 的 expr 语法是:$((表达式)),此处表达式中的 “*” 不需要转义符号 “\” 

示例:

编写expr1.sh脚本文件,内容如下:

#!/bin/bash
a=10
b=20

val=`expr $b % $a`
echo "b % a : $val"

if [ $a == $b ]
then
   echo "a 等于 b"
fi
if [ $a != $b ]
then
   echo "a 不等于 b"
fi

 运行结果如下:

1.扩展

对于算数运算,我们也可以这样的写法:

1.使用[]

#!/bin/bash
num1=10
num2=16

echo "num1+num2="$[num1+num2]
echo "num1-num2="$[num1-num2]
echo "num1*num2="$[num1*num2]
echo "num1/num2="$[num1/num2]
echo "num2/num1="$[num2/num1]

运行结果:

num1+num2=26
num1-num2=-6
num1*num2=160
num1/num2=0
num2/num1=1

注意:做除法运算的时候只显示整数部分,不显示小数部分。

2.使用(())

#!/bin/bash
num1=10
num2=16

echo "num1+num2="$(($num1+$num2))
echo "num1-num2="$(($num1-$num2))
echo "num1*num2="$((num1*num2))
echo "num1/num2="$((num1/num2))
echo "num2/num1="$((num2/num1))

运行结果:

注意:

  • 使用(())可以不用$符来获取变量值,它会自动解析变量 
  • 变量与符号之间可以不用空格

关系运算符

关系运算符只支持数字,不支持字符串,除非字符串的值是数字。

下表列出了常用的关系运算符,假定变量 a 为 10,变量 b 为 20:

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

布尔运算符

下表列出了常用的布尔运算符,假定变量 a 为 10,变量 b 为 20:

运算符说明举例
!非运算,表达式为 true 则返回 false,否则返回 true。[ ! false ] 返回 true。
-o或运算,有一个表达式为 true 则返回 true。[ $a -lt 20 -o $b -gt 100 ] 返回 true。
-a与运算,两个表达式都为 true 才返回 true。[ $a -lt 20 -a $b -gt 100 ] 返回 false。

注意:这里的0代表为true,1代表为false

4. 逻辑运算符
以下介绍 Shell 的逻辑运算符,假定变量 a 为 10,变量 b 为 20:

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

示例:

#!/bin/bash

a=10
b=20

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

执行结果如下:

区别于联系

[] 与[[ ]] 的区别:

  • [[ ]] 中逻辑组合可以使用 && || 符号
  • 而[] 里面逻辑组合可以用 -a -o

字符串运算符

下表列出了常用的字符串运算符,假定变量 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。

注意:这里的0代表为true,1代表为false

文件测试运算符

Shell 中的文件测试运算符允许你在脚本中测试文件的各种属性。这些运算符通常在方括号 [] 或者 [[]] 之间使用,并且用于 if 语句或 while 循环中进行条件判断。

在 Linux 系统中,文件类型多种多样,每种类型的文件都有其特定的功能和用途。以下是 Linux 中常见的几种文件类型:

  1. 普通文件(Regular Files): 这是最常见的文件类型,包含数据、文本、配置信息、程序代码等。在文件系统中表现为一个没有特殊标志的图标或文件名前没有特殊字符。

  2. 目录文件(Directory Files): 目录也是一种特殊的文件,用于组织其他文件和目录。在命令行中,目录通常以开头的斜杠 / 或点字符 . 表示。

  3. 设备文件(Device Files): 设备文件分为两种:

    • 块设备文件(Block Devices):如硬盘驱动器、光盘驱动器等,它们可以随机访问数据。
    • 字符设备文件(Character Devices):如串行端口、打印机等,它们提供顺序的数据流。
  4. 符号链接(Symbolic Links): 又称为软链接,类似于 Windows 中的快捷方式,指向另一个文件或目录的引用。符号链接本身是一个文件,其中包含目标文件的路径。

  5. 硬链接(Hard Links): 指向同一文件的多个文件名。硬链接直接指向文件的 inode(文件系统中的节点),而不是文件名。删除一个硬链接不会删除文件本身,直到最后一个硬链接被删除,文件才会被删除。

  6. 套接字文件(Socket Files): 用于进程间通信(IPC),可以是本地通信(Unix Domain Socket)或网络通信(TCP/IP Socket)。

  7. 管道文件(FIFOs或命名管道): FIFO 是一种特殊的文件,用于进程间通信,它创建了一个数据通道,可以被读取和写入。

  8. 特殊文件: 包括各种特殊目的的文件,比如 /proc/sys 目录下的文件,它们提供了对内核和硬件的访问。

在 Linux 命令行中,可以通过 ls -l 命令查看文件的详细信息,文件类型会显示在最左侧的字符中。例如,- 表示普通文件,d 表示目录,l 表示符号链接,b 表示块设备,c 表示字符设备,p 表示管道文件,s 表示套接字文件。

文件测试运算符用于检测 Unix 文件的各种属性。

属性检测描述如下:

操作符说明举例
-b file检测文件是否是块设备文件,如果是,则返回 true。[ -b $file ] 返回 false。
-c file检测文件是否是字符设备文件,如果是,则返回 true。[ -c $file ] 返回 false。
-d file检测文件是否是目录,如果是,则返回 true。[ -d $file ] 返回 false。
-f file检测文件是否是普通文件(既不是目录,也不是设备文件),如果是,则返回 true。[ -f $file ] 返回 true。
-g file检测文件是否设置了 SGID 位,如果是,则返回 true。[ -g $file ] 返回 false。
-k file检测文件是否设置了粘着位(Sticky Bit),如果是,则返回 true。[ -k $file ] 返回 false。
-p file检测文件是否是有名管道,如果是,则返回 true。[ -p $file ] 返回 false。
-u file检测文件是否设置了 SUID 位,如果是,则返回 true。[ -u $file ] 返回 false。
-r file检测文件是否可读,如果是,则返回 true。[ -r $file ] 返回 true。
-w file检测文件是否可写,如果是,则返回 true。[ -w $file ] 返回 true。
-x file检测文件是否可执行,如果是,则返回 true。[ -x $file ] 返回 true。
-s file检测文件是否为空(文件大小是否大于0),不为空返回 true。[ -s $file ] 返回 true。
-e file检测文件(包括目录)是否存在,如果是,则返回 true。[ -e $file ] 返回 true

expr命令详解

`expr` 是一个在 Unix 和类 Unix 系统(如 Linux)中使用的命令行工具,用于执行基本的数学和字符串表达式的解析和计算。`expr` 命令可以处理算术运算、字符串操作以及一些逻辑运算。

算术运算
`expr` 支持以下算术运算:
- 加法:`+`
- 减法:`-`
- 乘法:`*`
- 整除:`/`
- 求余:`%`

例如,计算两个数的和:

expr 5 + 3

字符串操作
`expr` 可以用来进行字符串的比较和截取:
- 比较字符串是否相等:`expr index string1 string2`
- 计算字符串的长度:`expr length string`
- 截取字符串:`expr substr string start end`

例如,获取字符串的长度:
expr length "Hello, world!"


截取字符串的一部分:
expr substr "Hello, world!" 7 6

bc命令详解

Bash shell内置了对整数运算的支持,但是并不支持浮点运算,而 linux bc(basic calculator)命令可以很方便的进行浮点运算.bc命令是Linux简单的计算器,能进行进制转换与计算。能转换的进制包括十六进制、十进制、八进制、二进制等。可以使用的运算符号包括(+)加法、(-)减法、(*)乘法、()除法、(^)指数、(%)余数等。

语法:

bc [options] [参数]

options

  • -i:强制进入交互式模式;
  • -l:定义使用的标准数学库;
  • -w:对POSIX bc的扩展给出警告信息;
  • -q:不打印正常的GNU bc环境信息;
  • -v:显示指令版本信息;
  • -h:显示指令的帮助信息。

示例:

更多内容请参考:05.Shell计算命令:bc命令详解-互动式的数学运算_哔哩哔哩_bilibili

八、流程控制语句

if...else语句

语法:

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





if condition1
then
    command1
elif condition2 
then 
    command2
else
    commandN
fi

if else 的 [...] 判断语句中大于使用 -gt,小于使用 -lt。

if [ "$a" -gt "$b" ]; then
    ...
fi

如果使用 ((...)) 作为判断语句,大于和小于可以直接使用 > 和 <。

if (( a > b )); then
    ...
fi

示例:

#!/bin/bash
a=10
b=20
if [ $a == $b ]
then
   echo "a 等于 b"
elif (( $a > $b ))
then
   echo "a 大于 b"
elif [ $a -lt $b ]
then
   echo "a 小于 b"
else
   echo "没有符合的条件"
fi

运行结果:

for语句

语法:

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

示例:

#!/bin/bash
for loop in 1 2 3 4 5
do
    echo "The value is: $loop"
done

运行结果:

while语句

语法:

while condition
do
    command
done

示例:

#!/bin/bash
int=1
while(( $int<=5 ))
do
    echo $int
    let "int++"
done

 运行结果:

until 语句

until 循环执行一系列命令直至条件为 true 时停止。

until 循环与 while 循环在处理方式上刚好相反。

一般 while 循环优于 until 循环,但在某些时候—也只是极少数情况下,until 循环更加有用。

until 语法格式:

until condition
do
    command
done

condition 一般为条件表达式,如果返回值为 false,则继续执行循环体内的语句,否则跳出循环。

以下实例我们使用 until 命令来输出 0 ~ 9 的数字:

#!/bin/bash
int=1
while(( $int<=5 ))
do
    echo $int
    let "int++"
done

运行结果:

case ... esac

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

可以用 case 语句匹配一个值与一个模式,如果匹配成功,执行相匹配的命令。

case ... esac 语法格式如下:

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

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

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

下面的脚本提示输入 1 到 4,与每一种模式进行匹配:

#!/bin/bash
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

运行结果:

跳出循环

在循环过程中,有时候需要在未达到循环结束条件时强制跳出循环,Shell 使用两个命令来实现该功能:break 和 continue

1.break 命令

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

下面的例子中,脚本进入死循环直至用户输入数字大于5。要跳出这个循环,返回到shell提示符下,需要使用break命令。

#!/bin/bash
while :
do
    echo -n "输入 1 到 5 之间的数字:"
    read aNum
    case $aNum in
        1|2|3|4|5) echo "你输入的数字为 $aNum!"
        ;;
        *) echo "你输入的数字不是 1 到 5 之间的! 游戏结束"
            break
        ;;
    esac
done

2.continue

continue 命令与 break 命令类似,只有一点差别,它不会跳出所有循环,仅仅跳出当前循环。

对上面的例子进行修改:

#!/bin/bash
while :
do
    echo -n "输入 1 到 5 之间的数字: "
    read aNum
    case $aNum in
        1|2|3|4|5) echo "你输入的数字为 $aNum!"
        ;;
        *) echo "你输入的数字不是 1 到 5 之间的!"
            continue
            echo "游戏结束"
        ;;
    esac
done

select语句

在 Bash shell 脚本中,select 命令提供了一种简单的菜单选择机制,允许用户从一组选项中做出选择。这对于创建交互式的脚本非常有用,可以用于构建命令行界面(CLI)应用或菜单驱动的脚本。

语法:

select NAME in LIST; do COMMANDS; done

示例:

#!/bin/bash

options=("Option 1" "Option 2" "Exit")

select opt in "${options[@]}"; do
    case $opt in
        "Option 1")
            echo "You chose option 1."
            ;;
        "Option 2")
            echo "You chose option 2."
            ;;
        "Exit")
            break
            ;;
        *) echo "Invalid option. Please select again." ;;
    esac
done

运行结果:

九、函数

自定义函数

语法:

[ function ] funname [()]

{

    action;

    [return int;]

}

说明:

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

下面的例子定义了一个函数并进行调用:

#!/bin/bash
demoFun(){
    echo "Hello World!"
}
echo "-----函数开始执行-----"
demoFun
echo "-----函数执行完毕-----"

运行结果:

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

#!/bin/bash

funWithReturn(){
    echo "这个函数会对输入的两个数字进行相加运算..."
    echo "输入第一个数字: "
    read aNum
    echo "输入第二个数字: "
    read anotherNum
    echo "两个数字分别为 $aNum 和 $anotherNum !"
    return $(($aNum+$anotherNum))
}
funWithReturn
echo "输入的两个数字之和为 $? !"

运行结果:

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

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

注意: return 语句只能返回一个介于 0 到 255 之间的整数,而两个输入数字的和可能超过这个范围。

要解决这个问题,您可以修改 return 语句,直接使用 echo 输出和而不是使用 return:

funWithReturn(){
    echo "这个函数会对输入的两个数字进行相加运算..."
    echo "输入第一个数字: "
    read aNum
    echo "输入第二个数字: "
    read anotherNum
    sum=$(($aNum + $anotherNum))
    echo "两个数字分别为 $aNum 和 $anotherNum !"
    echo $sum  # 输出两个数字的和
}

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

带参数的函数示例:

#!/bin/bash

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

运行结果:

 十、输入/输出重定向

输入输出重定向是 Unix/Linux shell 中一个非常强大的功能,它允许你改变命令的输入源或输出目的地,从而实现对数据流的控制。输入输出重定向可以让你避免不必要的屏幕输出,将数据保存到文件,或将数据从文件读入命令,甚至在多个命令之间传递数据。

重定向命令列表如下:

命令说明
command > file将输出重定向到 file。
command < file将输入重定向到 file。
command >> file将输出以追加的方式重定向到 file。
n > file将文件描述符为 n 的文件重定向到 file。
n >> file将文件描述符为 n 的文件以追加的方式重定向到 file。
n >& m将输出文件 m 和 n 合并。
n <& m将输入文件 m 和 n 合并。
<< tag将开始标记 tag 和结束标记 tag 之间的内容作为输入。

输出重定向

重定向一般通过在命令间插入特定的符号来实现。特别的,这些符号的语法如下所示:

command1 > file1

上面这个命令执行command1然后将输出的内容存入file1。

注意任何file1内的已经存在的内容将被新内容替代。如果要将新内容添加在文件末尾,请使用>>操作符。

示例:

重定向输入

我们先来学习一下wc命令,Linux的wc命令可以用来统计文件的字节个数、行数、单词数

语法:

wc [options] [文件名]

options选项如下:

在了解上述命令后,我们继续学习重定向输入:

一般情况下,每个 Unix/Linux 命令运行时都会打开三个文件:

  • 标准输入文件(stdin):stdin的文件描述符为0,Unix程序默认从stdin读取数据。
  • 标准输出文件(stdout):stdout 的文件描述符为1,Unix程序默认向stdout输出数据。
  • 标准错误文件(stderr):stderr的文件描述符为2,Unix程序会向stderr流中写入错误信息。

默认情况下,command > file 将 stdout 重定向到 file,command < file 将stdin 重定向到 file。

如果希望 stderr 重定向到 file,可以这样写:

command 2>file

如果希望 stderr 追加到 file 文件末尾,可以这样写:

command 2>>file

2 表示标准错误文件(stderr)。

如果希望将 stdout 和 stderr 合并后重定向到 file,可以这样写:

command >> file 2>&1

如果希望对 stdin 和 stdout 都重定向,可以这样写:

command < file1 >file2

command 命令将 stdin 重定向到 file1,将 stdout 重定向到 file2。

示例:

参考文章:Shell 教程 | 菜鸟教程 (runoob.com) 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1984414.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

趋动科技助力中国移动新型智算中心AI算力池化商用实践

由中国通信标准化协会、中国通信学会指导&#xff0c;CCSA TC610 SDN /NFV /AI标准与产业推进委员会主办的2024年云网智联大会于4月10日-11日在北京召开。 趋动科技联合申报的“中国移动新型智算中心AI算力池化商用实践”&#xff0c;获得2023年度SDN、NFV、网络AI优秀案例征集…

欧美农场小游戏 高端链游 休闲的欧美链游农场 【玫瑰庄园】 高端中英-欧美花园链游

#农场小游戏#链游【玫瑰庄园】 高端中英-欧美花园链游 玫瑰花园一、种子&#xff1a;种子分为五种&#xff1a;白玫瑰、红玫瑰、黑玫瑰、紫罗兰、郁金香。种子通过开启盲盒获得。二、种花&#xff1a;玩家开启盲盒获得的种子&#xff0c;会直接种下&#xff0c;种子种下后&…

深入浅出消息队列----【如何保证消息不重复?】

深入浅出消息队列----【如何保证消息不重复&#xff1f;】 消息一定会重复消息幂等消费改造业务符合天然幂等写法数据库唯一索引redis 唯一判断 本文仅是文章笔记&#xff0c;整理了原文章中重要的知识点、记录了个人的看法 文章来源&#xff1a;编程导航-鱼皮【yes哥深入浅出消…

从零开始的大模型训练教程

近年来&#xff0c;随着人工智能技术的迅猛发展&#xff0c;大模型&#xff08;Large Models&#xff09;成为了业界关注的焦点。这些模型&#xff0c;尤其是那些基于Transformer架构的自然语言处理模型&#xff0c;如GPT系列、BERT等&#xff0c;在各种任务上取得了前所未有的…

git add . 警告

这些警告是因为 Git 检测到你的文件使用了不同的换行符&#xff08;LF 或 CRLF&#xff09;&#xff0c;并提示在下次 Git 操作中将会统一换行符为 CRLF。这通常发生在跨平台协作时&#xff0c;例如在 Windows 环境下编辑的文件可能使用 CRLF&#xff0c;而在类 Unix 环境&…

数据结构:基于顺序表实现通讯录系统(含源码)

目录 一、前言 二、各个功能的实现 2.1 初始化通讯录 2.2 添加通讯录数据 2.3 查找通讯录数据 2.4 删除通讯录数据 2.5 修改通讯录数据 2.6 展示通讯录数据​编辑 2.7 销毁通讯录数据 三、添加菜单和测试 四、完整源码 sxb.h sxb.c contact.h contact.c test.c 一、前…

ROS智能移动机器人实训

0.前言 1.任务 1.1.任务实训任务 1.使用/voice_aiui等语音服务完成基本的语音聊天(需唤醒词“元宝”)。 2.语音多点导航 3.语音单点导航 1.2.智能机器人仿真任务 1.3.智能机器人实物操作任务 2.目的 3&#xff0e;使用环境 4.综合项目实验 任务实训 问题 解决办法…

LinuxIO之文件系统的实现

Ext2/3/4 的layout文件系统的一致性&#xff1a; append一个文件的全流程掉电与文件系统的一致性fsck文件系统的日志ext4 mount选项文件系统的debug和dumpCopy On Write 文件系统&#xff1a; btrfs 预备知识&#xff1a;数据库里的transaction(事务)有什么特性&#xff1f; …

前端高薪岗位之大模型端上部署及训练

自2022年ChatGPT发布以来&#xff0c;以大模型为依托的AIGC相关的应用产品&#xff0c;比如ChatGPT、Midjourney、Stable Diffusion等&#xff0c;在社交网站的讨论热度持续攀升&#xff0c;引发了较大范围的好奇与关注。 目前&#xff0c;国内外各个科技大厂在大模型的端侧部…

手机k歌麦克风哪种好,口碑最好的k歌麦克风是哪款,麦克风推荐

​当我们谈论到演讲、表演或者录制视频时&#xff0c;一个高质量的无线麦克风能够使得整个体验提升至一个全新的水平。它不仅能够保证声音的清晰度和真实度&#xff0c;还能够让使用者在演讲或者表演时更加自信和舒适。基于对市场的深入研究和用户体验的考量&#xff0c;我挑选…

Langchain-Chatchat+Xinference集成部署

Langchain-ChatchatXinference集成部署 安装环境&#xff1a; 系统&#xff1a;Anolis OS 8.9 python版本&#xff1a;Python 3.9.19 Langchain-Chatchat版本&#xff1a;0.3.1.3 Xinference版本&#xff1a;v0.13.3 模型选择&#xff08;下载时需要科学上网&#xff09;&#…

一些常见的中间件漏洞

Tomcat 之CVE-2017-12615 靶场搭建使用vulhub-master/tomcat/CVE-2017-12615 第一步、访问网站 第二步、首页抓包改为put方式提交 网上找一个jsp的一句话木马 使用webshell工具链接即可 Tomcat 之tomcat8 vulhub-master/tomcat/tomcat8 继续访问页面 这次我们点击登录&…

ES6中的Promise、async、await,超详细讲解!

Promise是es6引入的异步编程新解决方案&#xff0c;Promise实例和原型上有reject、resolve、all、then、catch、finally等多个方法&#xff0c;语法上promise就是一个构造函数&#xff0c;用来封装异步操作并可以获取其成功或失败的结果&#xff0c;本篇文章主要介绍了ES6中的P…

spring原理(第十天)

jdk 和 cglib 在 Spring 中的统一 Spring 中对切点、通知、切面的抽象如下 切点&#xff1a;接口 Pointcut&#xff0c;典型实现 AspectJExpressionPointcut 通知&#xff1a;典型接口为 MethodInterceptor 代表环绕通知 切面&#xff1a;Advisor&#xff0c;包含一个 Advic…

政务服务技能竞赛规则流程方案

此次政务服务技能竞赛以“强服务、优素质、促提升、共发展”为目标&#xff0c;通过以赛代练、以赛促建、比学赶超、全面提升&#xff0c;激发各级政务服务工作人员学政策、钻业务、练技能的热情和积极性&#xff0c;全面推动行政效能提升与营商环境建设&#xff0c;铸造新时代…

pytorch和deep learning技巧和bug解决方法短篇收集

有一些几句话就可以说明白的观点或者解决的的问题&#xff0c;小虎单独收集到这里。 torch.hub.load how does it work 下载预训练模型再载入&#xff0c;用程序下载链接可能失效。 model torch.hub.load(ultralytics/yolov5, yolov5s)model torch.hub.load(ultralytics/y…

IROS2024 | DarkGS:学习神经照明和3D高斯重新照明,用于黑暗中机器人探索

DarkGS&#xff1a;学习神经照明和3D高斯重新照明&#xff0c;用于黑暗中机器人探索 论文标题&#xff1a;DarkGS: Learning Neural Illumination and 3D Gaussians Relighting for Robotic Exploration in the Dark 论文地址&#xff1a;https://arxiv.org/abs/2403.10814 研…

数据开发/数仓工程师上手指南(七)CDM-DWS层搭建规范及流程

前言 进入到了CMD公共数据层的结尾最后一层-DWS层了&#xff0c;该层基本就是直接与业务强关联&#xff0c;也就是说产品提出的需求&#xff0c;或是报表、用户画像统计好还是数据大屏都是在这一层给处理好数据&#xff0c;再放入ADS层&#xff0c;然后我们只需要在BI里面配备…

【数据结构】——堆的实现(赋源码)

堆的概念与结构 堆(Heap)是计算机科学中一类特殊的数据结构&#xff0c;是最高效的优先级队列。堆通常是一个可以被看作一棵完全二叉树的数组对象。 堆的性质: 堆中某个结点的值总是不大于或不小于其父结点的值&#xff1b; 堆总是一棵完全二叉树。 堆的物理结构本质上是顺序…

PDF怎么转Word?分享二个简单的方法

很多小伙伴在工作学习的时候&#xff0c;经常会遇到别人发来的PDF文件。PDF 文件用于查看资料非常方便&#xff0c;因为它们的布局稳定&#xff0c;在大多数设备上都可以显示相同的布局。 如果我们需要将其转换为Word&#xff0c;如何转换呢&#xff1f;许多人不知道如何转换。…