欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 新闻 > 焦点 > 02-shell 脚本语言

02-shell 脚本语言

2025/1/2 20:15:45 来源:https://blog.csdn.net/qq_63958145/article/details/144808313  浏览:    关键词:02-shell 脚本语言

一、shell 的概述

1.脚本语言与 C/C++的区别

  • 对比:
  1. C/C++是编译型语言:编写好的代码需要经过预处理、编译、汇编、链接生成可执行文件,运行可执行文件得到进程,是静态语言;
  2. 脚本语言:编写代码,脚本解析器逐行分析执行,脚本语言对代码的格式要求高,要严格按照其语法要求编写,有时候多一个空格都不行,是动态语言。

2.shell 的介绍

shell 既是应用程序(shell 解析器),又是程序设计语言(shell 脚本语言)。

常见的 shell 解析器有:sh、ash、bash

  • 通过命令查看默认解析器
edu@edu:~$ echo $SHELL
/bin/bash # 解析器
edu@edu:~$ env # 查看系统环境变量
XDG_SESSION_ID=1
TERM=xterm
SHELL=/bin/bash
SSH_CLIENT=192.168.1.5 50316 22
SSH_TTY=/dev/pts/23
USER=edu......
  • 说明:
    1. 当前系统默认的解析器是 bash 解析器;
    2. shell 里面查看某个变量的值,需要在变量名前加 $ 美元符号;
    3. env 命令用于查看系统的环境变量;
    4. shell 脚本是用户操作内核数据的途径之一;
    5. 可以通过 shell 脚本完成批处理,完成大量重复执行的动作。

3.Linux 自动调用的脚本

linux 自动调用/etc/profile ~/.bashrc两个脚本,这两个文件都是用来配置配置环境的。

  1. /etc/profile 用户登录的时候自动调用该文件,用于配置系统的环境,即修改环境变量的话,当前系统所有用户的配置都会发生改变;
  2. ~/.bashrc 用户登录、用户打开终端时自动调用该文件,用于配置用户环境变量,即只在当前用户有效。

二、shell 语法

1.第一个 shell 脚本

  • 代码演示
#!/bin/bash# 打印一句话
echo "hello world"
  • 说明:
  • #!表示指明解析器为 bash 解析器;
  • # 后面跟注释;
  • 通过 vim 创建的文件没有可执行权限,需要通过chmod +x 文件名为其添加可执行权限;
edu@edu:~/study/my_code$ ls 01-first_code.sh -lh # 查看脚本文件权限
-rw-rw-r-- 1 edu edu 50 1228 15:46 01-first_code.sh # 没有 x 可执行权限
edu@edu:~/study/my_code$ chmod +x 01-first_code.sh # 添加可执行权限
edu@edu:~/study/my_code$ ls 01-first_code.sh -lh
-rwxrwxr-x 1 edu edu 50 1228 15:46 01-first_code.sh
edu@edu:~/study/my_code$ ./01-first_code.sh # 执行脚本
hello world # 运行结果

多行注释可以用:

<<COMMENT
要注释的多行代码
COMMENT

2.运行脚本的三种方法

  1. ./脚本文件 :先使用文件中 #! 指定的解析器解析,如果该解析器不存在 使用系统默认的解析器解析,是当前 shell 开启一个子 shell来执行,不会影响当前 shell 的配置;
  2. bash 脚本文件:先直接使用 bash 解析器解析,如果 bash 解析器不存在,再使用系统默认的解析器,是当前 shell 开启一个子 shell来执行,不会影响当前 shell 的配置;
  3. . 脚本文件:直接使用系统默认的解析器解析,在当前 shell 执行,如果需要脚本修改当前 shell 的环境配置,选用这种方法运行。

3.shell 的变量

3.1变量的定义及读取

  • 代码演示
#!/bin/bash# 定义一个变量
num=100
echo "num = $num" # 100
  • 运行结果
num = 100
data = 100
  • 说明:
    1. 赋值的时候等号两边不能有空格;
    2. shell 脚本的变量没有类型;
    3. 取变量的值等读操作的时候,变量的左边要加美元符号$。

3.2 unset 清除一个变量

如果某个已经定义的变量我们不想用了,可以将其清除掉。

  • 代码演示
num=100
echo "num = $num"
unset num
echo "num = $num"
  • 运行结果
num = 100
num =
  • 说明:可以看到,访问被清除的变量访问的是空。

3.3变量获取键盘输入

  • 第一种方法:read 变量名
echo "请输入一个整数:"
read num1
echo "num1 = $num1"
  • 运行结果
请输入一个整数:
55
num1 = 55
  • 说明:这种方法虽然能够获取,但可以看到提示信息和输入不在同一行,不够美观。

  • 第二种较美观的方法:read -p "提示信息" 变量名

# 为一个变量值获取
read -p "请输入一个整数:" num
echo "num = $num"
# 为多个变量值获取
read -p "请输入两个整数:" num1 num2
echo "num1 = $num1, num2 = $num2"
  • 运行结果
请输入一个整数:100
num = 100
请输入两个整数:100 200
num1 = 100, num2 = 200
  • 说明:

    1. 注意 -p 要在 read 之后,提示信息之前;
    2. 当为多个变量获取输入的时候,变量名之间有空格隔开。
  • 获取带空格的字符串

# 错误的方式
read -p "请输入一个字符串:" str1 str2
echo "str1 = $str1, str2 = $str2"
# 正确的方式
read -p "请输入一个字符串:" str
echo "str = $str"
  • 运行结果
请输入一个字符串:hello world my name is jack
str1 = hello, str2 = world my name is jack
请输入一个字符串:hello world my name is jack
str = hello world my name is jack
  • 说明:
    1. 从第一个案例可以看出,第一个变量在遇到空格后就结束获取了,但第二个即最后一个变量会获取剩余的使用,包括空格;
    2. 要键盘获取带空格的字符串,只能一次对一个变量操作。

3.4只读变量

  • 只读变量:在定义变量的时候在前面加上 readonly 修饰
readonly num=10
echo "num = $num"
num=20
echo "num = $num"
  • 运行结果
num = 10
./02-shell变量.sh: 行 35: num: 只读变量 # 提示信息,不可修改
num = 10

3.5导出环境变量

环境变量:是操作系统自动识别的变量,通过 evn 命令可以查看系统环境变量,前面有演示。

导出环境变量:就是将自定义变量存放在 env 中,使其成为系统的环境变量。

  • 通过 export 自定义变量导入环境变量
# 导入环境变量
export DATA=10086
  • 终端运行的时候需要通过:source 脚本文件运行才能在当前 shell 导入环境变量
edu@edu:~/study/my_code$ source 02-shell变量.sh
edu@edu:~/study/my_code$ echo $DATA # 终端命令查看系统环境变量
10086

3.6单引号和双引号的区别

  • 代码演示
num=10
echo "num = $num"
echo 'num = $num'
  • 运行结果
num = 10
num = $num
  • 说明:
    1. 双引号会解析出变量的值;
    2. 单引号会将其当成字符串处理。

3.7预设变量

  • 常用的预设变量

  • $#:传给 shell 脚本参数的个数,即调用脚本的时候后面跟的参数个数;

  • $*:传给 shell 脚本参数的内容,这里是全部内容;

  • $1、$2、$3、…、$9:运行脚本时传递给其的参数,访问时用空格隔开;

  • $?:命令执行后返回的状态 ,用于检查上一个命令执行是否正确(在 Linux 中,状态为 0 表示该命令正确执行,任何非 0 值表示命令出错);

  • $0:当前执行的进程名;

  • $$:当前进程的进程号 ,最常用作临时文件的名字以保证临时文件不会重复。

  • 代码演示

echo "参数的个数:$#"
echo "所有参数:$*"
echo "第一个参数:$1"
echo "第二个参数:$2"
echo "第三个参数:$3"
echo "上一条命令执行的状态:$?"
echo "当前进程名:$0"
echo "当前进程号:$$"
ls # 脚本文件里输入命令
  • 运行结果
edu@edu:~/study/my_code$ ./02-shell变量.sh aa bb cc
参数的个数:3
所有参数:aa bb cc
第一个参数:aa
第二个参数:bb
第三个参数:cc
上一条命令执行的状态:0
当前进程名:./02-shell变量.sh
当前进程号:7739
01-first_code.sh  02-shell变量.sh # 命令同样执行将结果输出到终端

3.8变量的特殊用法

双引号和单引号上面已经介绍过了

  • 反引号里面写系统命令,会将命令执行的结果赋值给变量:
fileList=`ls`
echo "$fileList"
  • 运行结果
edu@edu:~/study/my_code$ source 02-shell变量.sh
01-first_code.sh
02-shell变量.sh
  • 转义字符:同C语言,但正常情况下转义字符不生效,需要加 -e 选项
echo "hello\nworld"
echo -e "hello\nworld" # -e 加在 echo 后,字符串前
  • 运行结果
hello\nworld
hello
world
  • 子 shell ,(命令序列)即将要完成的内容通过创建一个子 shell 来完成
num=100
(num=200echo "num = $num"
)
echo "num = $num"
  • 运行结果
num = 200
num = 100 # 没有影响到当前 shell 的值
  • 运行效果类似于C语言里面的局部变量和全局变量同名的现象,其实小括号里是当前 shell 创建的一个子 shell,为了避免运行对当前 shell 环境产生影响,放到子 shell 运行。

  • 当前 shell ,{ 命令序列 },强调在当前 shell 种执行,会影响到当前 shell,注意:中括号两边空格

num=100
{num=200echo "num = $num"
}
echo "num = $num"
  • 运行结果
num = 200
num = 200 # 对当前 shell 的值做出了修改

三、条件测试语句

1.测试语句语法

  • 语法
test 条件语句
[ 条件语句 ] #[]有空格

测试包括:对文件测试、字符串测试、数字测试、复合测试,测试语句一般与条件语句联合使用。

2.文件测试

对文件的测试包含以下几个方面的测试:

-e 测试存在
-d 测试是目录
-f 测试是文件
-r 文件可读
-w 文件可写
-x 文件可执行
-L 符号连接
-c 是否字符设备
-b 是否块设备
-s 文件非空
# 上面条件满足,运行状态为0,否则非0
  • 代码演示
fileName="a.txt"
ls -lh "a.txt" # 查看文件的详细信息用于结果对比test -e $fileName
# 查看上条语句执行的结果
echo $?test -d $fileName
echo $?test -f $fileName
echo $?[ -r $fileName ]
echo $?[ -w $fileName ]
echo $?[ -x $fileName ]
echo $?[ -s $fileName ]
echo $?
  • 运行结果
-rw-rw-r-- 1 edu edu 0 12月 28 20:18 a.txt
0 # 文件存在
1 # 不是目录
0 # 是文件
0 # 可读
0 # 可写
1 # 不可执行
1 # 文件为空

3.字符串测试

3.1基础语法

  • 语法
test stroperator “str”
test “str1” stroperator “str2”
[ stroperator “str” ]
[ “str1” stroperator “str2”]
  • 说明:

    1. stroperator:是用于字符串判断的操作符,或选项。包括 := 两个字符串相等, != 两个字符串不相等, -z 空串, -n 非空串;
    2. []两边记得加空格;
  • 代码演示

str1=hello
str2=hello
str3=hallotest -z $str1
echo $?[ -n $str1 ]
echo $?test $str1 = $str2
echo $?[ $str1 = $str3 ]
echo $?
  • 运行结果
1 # 不为空
0 # 非空
0 # 相等
1 # 不相等
  • 说明:
    1. 在比较过程中是比较变量对应的值,而不是变量名,因此要先读到变量的值,就需要加 $;
    2. 判断是否相等的时候等号两边加空格。

3.2扩展语法

  • 代码演示
str=aaa:bbb:cc:dddd
# 求字符串的长度
echo ${#str}
# 从第 n 个字符取字符串
echo ${str:3}
# 从第 n 个字符取字符串,取指定个数
echo ${str:3:5}
# 从左往右替换指定第一个字符
echo ${str/:/*}
# 从左往右替换指定的所有字符
echo ${str//:/*}
  • 运行结果
15
:bbb:cc:dddd
:bbb:
aaa*bbb:cc:dddd
aaa*bbb*cc*dddd

4.数值测试

4.1基础语法

  • 语法
test num1 numoperator num2
[ num1 numoperator num2 ]numoperator可选参数为:
-eq 数值相等
-ne 数值不相等
-gt 左数 大于 右数
-ge 左数 大于等于 右数
-le 左数 小于等于 右数
-lt 左数 小于 右数
满足,表达式的状态为0,否则非0
  • 代码演示
num1=10
num2=20test $num1 -eq $num2
echo $?test $num1 -ne $num2
echo $?[ $num1 -gt $num2 ]
echo $?[ $num1 -lt $num2 ]
echo $?
  • 运行结果:
1 # 不相等
0 # 不相等
1 # 不大于
0 # 小于

4.2扩展语法

  • 代码演示
echo ${data:-100}
data=200
echo ${data:-100}echo ${data1:=300}
echo $data1
  • 运行结果
100
200
300
300
  • 说明:
    1. echo ${data:-100}:当 data 存在时,表达式的结果就是 data 的值,不存在的时候,表达式的结果就是100;
    2. echo ${data1:=300}:当 data1 存在时,表达式的结果就是 data1 的值,不存在时,表达式的结果就是300,并且还会创建一个变量 data1 将其赋值为300。

5.符合测试

符合测试类似于C语言中的逻辑与、逻辑或。

5.1单条件判断

command1 && command2

&& 左边命令执行成功,shell 才执行 && 右边的命令;

command1 || command2

|| 左边的命令未执行成功,shell 才执行 || 右边的命令。

  • 案例:键盘输入一个数,判断是否在 0 ~ 100 之间
read -p "请输入一个数:" numtest $num -gt 0 && test $num -lt 100
echo $?[ $num -gt 0 ] && [ $num -lt 100 ]
echo $?
  • 运行结果
请输入一个数:50
0
0
edu@edu:~/study/my_code$ ./02-shell变量.sh
请输入一个数:120
1
1

5.2多重条件判断

  1. -a :两种状态同时成立;
  2. -o :两种状态成立一个;
  3. !:相反状态。
  • 上面的案例,通过多重条件判断实现
read -p "请输入一个数:" numtest $num -gt 0 -a $num -lt 100
echo $?[ $num -gt 0 -a $num -lt 100 ]
echo $?
  • 运行结果
请输入一个数:150
1
1
edu@edu:~/study/my_code$ ./02-shell变量.sh
请输入一个数:50
0
0

6.if 条件语句

6.1if 语句的三种形式

1.单条件语句

if [ 条件1 ];then语句1
fi

2.双条件语句

if [ 条件1 ];then语句1
else语句2
fi

3.多条件语句

if [ 条件1 ];then语句1
elif [ 条件2 ];then语句2
else语句3
fi
  • 说明:[ 条件1 ]就是我们上面学习的测试语句,记得中括号两侧加空格。

6.2if 语句案例

  • 案例:键盘输入文件名,判断当前目录是否有此文件,如果有请输出文件内容,如果没有,创建此文件,并键盘输入文件内容写入文件,并输出内容。
read -p "请输入文件名:" fileName
# 判断文件是否存在且非空
if [ -e $fileName -a -s $fileName ];thencat $fileName 
elsetouch $fileNameread -p "请输入内容:" content# 将临时变量的值输入到文件echo $content >> $fileNamecat $fileName 
fi
  • 运行结果
edu@edu:~/study/my_code$ ls
01-first_code.sh  02-shell变量.sh  a.txt
edu@edu:~/study/my_code$ ./02-shell变量.sh
请输入文件名:a.txt
hello a.txt
edu@edu:~/study/my_code$ ./02-shell变量.sh
请输入文件名:b.txt
请输入内容:hello b.txt
hello b.txt

7.case 语句

7.1case 语句语法

case $变量 in值1)语句 1;;值2)语句 2;; *)语句 3;;exit 1 #退出 shell
esac
  • 说明:
    1. 这里的值1)相当于C语言中的case 值1*)相当于 default;
    2. ;; 相当于C语言中的 break。

7.2 case 案例

  • 代码演示
read -p "请输入(hello 或 bye):" text
case $text inh* | H*)echo "你好";;b* | B*)echo "再见";;
esac 
  • 运行结果
请输入(hello 或 bye):hello
你好
edu@edu:~/study/my_code$ ./02-shell变量.sh
请输入(hello 或 bye):By
再见
  • 说明:h* | H*中的 * 是通配符,可以匹配任意字符,这里是匹配任何以 h 或 H 开头的字符串。

四、循环语句

1.for 循环语句

1.1 for 循环的第一种格式

  • 语法
for (( 初始值; 循环条件; 步进语句 ))
do循环体
done
  • 案例:计算 1 ~ 100 累加和
declare -i i=0
declare -i num=0for (( i=1,num=0; i<=100; i++ ))
donum=$num+$i
doneecho "计算结果num = $num"
  • 运行结果
计算结果num = 5050
  • 说明:
    1. 因为 shell 变量没有数据类型,因此需要通过declare -i i=0强制指定 i 为 int 类型的数据;
    2. for 循环双小括号两侧留有空格。

1.2 for 循环的第二种格式

  • 语法
for var in con1 con2 con3 ... con100
do
循环体
done
第 1 次循环的时候 var 的值为 con1
第 2 次循环的时候 var 的值为 con2
第 3 次循环的时候 var 的值为 con3
.... 
第 n 次循环的时候 var 的值为 conn
类似于 python 里面的 for 循环,for i in 可迭代对象
  • 代码演示
for num in 1 2 3 4
doecho "num = $num"
done
  • 运行结果
num = 1
num = 2
num = 3
num = 4

1.3 for 循环案例

  • 扫描当前目录,并且判断是文件还是目录
for file in `ls -a`
doif [ -f $file ];thenecho "$file是文件"elif [ -d $file ];thenecho "$file是目录"fi    
done
  • 运行结果
.是目录
..是目录
01-first_code.sh是文件
02-shell变量.sh是文件
a.txt是文件
b.txt是文件
test是目录

2. while 循环

  • 语法
while [ 循环条件 ]
do循环语句
done
条件满足进入循环,不满足退出循环
  • 计算 0 ~ 100 的累加和
declare -i i=1
declare -i num=0while [ $i -le 100 ]
donum=$num+$ii=$i+1
done
echo "计算结果num = $num"
  • 运行结果
计算结果num = 5050
  • 说明:判断符号还有自增只能在 for 循环里面用, while 循环里面语法错误。

3. until 循环

  • 语法
until [ 条件 ]
do循环体
done
直到条件满足退出循环,否则一直循环到条件满足
  • 计算 0 ~ 100 的累加和
declare -i i=1
declare -i num=0until [ $i -gt 100 ]
donum=$num+$ii=$i+1
done
echo "计算结果num = $num"
  • 运行结果
计算结果num = 5050

五、函数

1.函数定义格式

  • 语法
格式一:
函数名()
{函数体
}
格式二:(推荐)
function 函数名() # 函数没有形参,只在调用的时候传实参
{函数体
}

2.函数调用格式

函数名 实参1 实参2 实参3 # 实参间用空格隔开
# 函数内部使用实参,结合前面学习的知识
$1==实参1
$2==实参2
$3==实参3
  • 案例:定义一个函数,键盘获取输入,求两个数的和
declare -i num1
declare -i num2function myAdd()
{declare -i retret=$1+$2return $ret
}
read -p "请输入两个数:" num1 num2
myAdd $num1 $num2
echo "计算结果 = $?"
  • 运行结果
请输入两个数:10 20
计算结果 = 30
  • 涉及到多文件编程的时候,只需要在主脚本文件里面通过source 脚本文件包含其它脚本,就能使用其它脚本里面的函数了。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com