当前位置: 首页 > news >正文

今天我们开始学习shell编程语言

一、Shell脚本语言的基本结构


1、Shell脚本的用途:

  • 自动化常用命令

  • 执行系统管理和故障排除

  • 创建简单的应用程序

  • 处理文本或文件

2、 Shell脚本基本结构:

Shell脚本编程:是基于过程式,解释执行的语言

编程语言函数:指将具有特定功能的代码编写在一个有限的区块内并且取名

编程语言的基本结构:

  • 各种系统命令的组合

  • 数据存储:变量,数组,变量赋值:变量名=$(赋值符)

  • 表达式:a+b

  • 控制语句:if······then······条件语句、case、for循环语句、while

shell脚本:包含一些命令或声明,并符合一定格式的文本文件(写shell脚本时一定严格按照规范写,脚本名一定要用英文表示)

格式要求:首行执行shebang机制

#声明后续语句是通过那种语言写的
#!/bin/bash
#!/usr/bin/python
#!/usr/bin/perl

3、 创建Shell脚本过程

1.使用vim创建文本文件,第一行必须包括shell声明序列:

[root@localhost ~]# vim one.sh
#!/bin/bash
#name:lll
#版本号:1.1.1
#time:2025.1.1
#随便
#无注意事项
#无需更新
echo "my hostname is 'nblt'"
echo "Time is 'date +'%F %T''"

2.加执行权限,给予执行权限,在命令行上指定脚本的绝对或相对路径

[root@localhost ~]# chmod +x one.sh

3.运行脚本,直接运行解释器,将脚本作为解释器程序的参数运行

[root@localhost ~]# /root/one.sh
my hostname is 'nblt'
Time is 'date +'%F %T''

4、 脚本注释规范

  • 第一行一般为调用使用的语言

  • 程序名,避免更改文件名为无法找到正确的文件

  • 版本号

  • 更改后的时间

  • 作者相关信息

  • 该程序的作用,及注意事项

  • 最后是各版本的更新简要说明

5、第一个脚本

[root@localhost ~]# cat one.sh
#!/bin/bash
#name:lll
#版本号:1.1.1
#time:2025.1.1
#随便
#无注意事项
#无需更新
echo "my hostname is 'nblt'"
echo "Time is 'date +'%F %T''"
[root@localhost ~]# chmod +x one.sh
[root@localhost ~]# /root/one.sh
my hostname is 'nblt'
Time is 'date +'%F %T'

6、 执行脚本

1、增加执行权限,执行脚本时会创建一个子shell,不影响现有的shell环境

[root@localhost ~]# chmod +x one.sh
[root@localhost ~]# ./one.sh
my hostname is 'nblt'
Time is 'date +'%F %T''
[root@localhost ~]# /root/one.sh
my hostname is 'nblt'
Time is 'date +'%F %T''

2、使用 . 或者source,执行脚本时不会创建一个子shell,会影响现有的shell环境

source one.sh
. one.sh

注意:尽量不要使用该方式执行脚本!!!

7、脚本错误

  • 语法错误,会导致后续的命令不继续执行,可以用bash -n shellname检查错误

  • 命令错误,后续的命令还会继续,可以使用bash -x shellname检查

  • 逻辑错误,只能使用bash -x进行观察

二、Shell脚本语言的变量用法详解


1、变量

变量表示命名的内存空间,将数据放在内存空间中,通过变量名引用,获取数据

2、 变量类型

变量类型:

  • 内置变量:如PS1,PATH,UID,HOSTNAME,HISTSIZE

  • 用户自定义变量

  • 预定义变量

  • 位置变量

不同的变量存放的数据不同,决定了以下:

  1. 数据存储方式

  2. 参与的计算

  3. 表示的数据范围

变量数据类型:

  • 字符串

  • 数值:整型,浮点型(小数)、bash不支持浮点数

3、 Shell中变量命名法则

  • 不能使用程序中的保留字,如:if,for

  • 只能使用数字,字母及下划线,且不能以数字开头

  • 见名思意,用英文名字,并体现真正含义

  • 统一命名规则:驼峰命名法

  • 全局变量名大写

  • 局部变量小写

  • 函数名小写

4、 变量定义和引用

变量的生效范围(变量作用域)

  • 普通变量:生效范围为当前shell进程;对当前shell之外的其他shell进程,包括当前shell的子shell进程均无效

  • 环境变量:生效范围为当前shell进程及其子进程

  • 本地变量:生效范围为当前shell进程中某代码片段,通常指函数

变量赋值:

name="value"
​
value可以是以下多种类型
直接字符串:name='root'
变量引用:name="$USER"
命令应用:name=`command`  || name=$(command)
通配符:FILE=/etc/* /*表示etc目录下所有的文件名*/

注意:变量赋值是临时生效,当退出终端后,变量会自动删除,无法持久保存。

变量引用:

$name
${name}

弱引用和强引用:

  • “$name”:弱引用,其中的变量引用会被替换成为变量值

  • ‘$name’:强引用,其中的变量引用不会被替换成变量值,而保持原字符串

实例:

[root@localhost ~]# name='MIKE'
[root@localhost ~]# NAME="$USER"
[root@localhost ~]# hostname=`hostname`
[root@localhost ~]# echo "My name is $name"
My name is MIKE
[root@localhost ~]# echo "My name is $NAME"
My name is root
[root@localhost ~]# echo "My hostname is $hostname"
My hostname is localhost
[root@localhost ~]# 
[root@localhost ~]# NUM=`seq 10`
[root@localhost ~]# echo $NUM
1 2 3 4 5 6 7 8 9 10
[root@localhost ~]# echo "$NUM"
1
2
3
4
5
6
7
8
9
10
[root@localhost ~]# 

查看已定义的所有变量:

[root@localhost ~]# set

删除变量

实例:

[root@localhost ~]# name=Mike
[root@localhost ~]# echo $name
Mike
[root@localhost ~]# unset name
[root@localhost ~]# echo $name

实例:"{}"的使用

[root@localhost ~]# name=mage
[root@localhost ~]# age=20
[root@localhost ~]# echo $name
mage
[root@localhost ~]# echo $name $age
mage 20
[root@localhost ~]# echo $name_$age
20
[root@localhost ~]# echo ${name}_$age
mage_20
[root@localhost ~]# 

利用变量实现动态命令

[root@localhost ~]# CMD=hostname
[root@localhost ~]# $CMD
localhost
[root@localhost ~]# 

5、 环境变量

环境变量:

  • 可以使子进程(包括孙子进程)继承父进程的变量,但是无法让父进程使用子进程的变量。

  • 一旦子进程修改了从父进程继承的变量,将会传递新的值给孙子进程

  • 一般只在配置文件中使用,在脚本中较少使用

课程引入:普通变量生效的范围与环境变量生效的范围

[root@localhost ~]# vim father.sh
#!/bin/bash
name=father
echo "father.sh:name=$name"
echo "fatther is PID=$BASHPID"
./son.sh
[root@localhost ~]# vim son.sh
#!/bin/bash
echo "son.sh:name=$name"
name=son
echo "son.sh:name=$name"
echo "son.sh PID is $BASHPID"
echo "son.sh father pid is $PPID"
[root@localhost ~]# chmod -R +x /*
[root@localhost ~]# ./father.sh
father.sh:name=father
fatther is PID=110924
son.sh:name=
son.sh:name=son
son.sh PID is 110925
son.sh father pid is 110924

变量声明和赋值:

export name=VALUE
declare -x name =VALUE
​
#或者先赋值再声明~
​
value可以是以下多种类型
直接字符串:name='root'
变量引用:name="$USER"
命令应用:name=`command`  || name=$(command)
通配符:FILE=/etc/* /*表示etc目录下所有的文件名*/

{declare命令详解:(了解)

declare 为 shell 指令,在第一种语法中可用来声明变量并设置变量的属性([rix]即为变量的属性),在第二种语法中可用来显示 shell 函数。若不加上任何参数,则会显示全部的 shell 变量与函数(与执行 set 指令的效果相同)

语法

declare [+/-][rxi][变量名称=设置值] 或 declare -f

参数说明

  • +/-  "-“可用来指定变量的属性,”+"则是取消变量所设的属性。

  • -f   仅显示函数

  • r   将变量声明为只读变量。注意,一旦设置为只读变量,既不能修改变量的值也不能删除变量,甚至不能通过+r取消只 读属性

  • x   指定的变量会成为环境变量,可供shell以外的程序来使用

  • i   将变量声明为整数型(integer)

  • p 显示指定变量的被声明类型。

实例

1.声明整数型变量

#!/bin/bash
declare -i ab //声明整数型变量
ab=56 //改变变量内容
echo $ab //显示变量内容
​
--->
56

改变变量属性

#!/bin/bash
#声明整数型变量
declare -i ef 
ef=1
echo $ef
#变量赋值,赋予文本值
ef="wer"
echo $ef
#取消变量属性
declare +i ef
ef="wer"
echo $ef

3.设置变量只读

#!/bin/bash
declare -r ab #设置变量为只读
ab=88 #改变变量内容
echo $ab #显示变量内容
​
--->
declare.sh:行3: ab: 只读变量

4.声明数组变量

#!/bin/bash
#声明数组变量
declare -a cd
cd[0]=a
cd[1]=b
cd[2]=c
#输出数组的指定内容
echo ${cd[1]}
#显示整个数组变量内容
echo ${cd[@]}

5.显示函数

#!/bin/bash
#声明函数
declare -f 
function command_not_found_handle(){if [ -x /usr/lib/command_not_found_handle ];then/usr/bin/python /usr/lib/command_not_found_handle -- $1;return $?;elseif [ -x /usr/share/command_not_found_handle ];then/usr/bin/python /usr/share/command_not_found_handle --$1;return $?;elsereturn 127;fi;fi;
}

变量引用:

$name
${name}

完善课程导入:

[root@localhost ~]# vim shell/father.sh 
#!/bin/bash
NAME=father
export NAME
echo "father.sh:NAME=$NAME"
echo "fatther is PID=$BASHPID"
shell/son.sh
​
[root@localhost ~]#vim shell/son.sh
#!/bin/bash
echo "son.sh:NAME=$NAME"
NAME=son
echo "son.sh:NAME=$NAME"
echo "son.sh PID is $BASHPID"
echo "son.sh father pid is $PPID"
sleep 100
​
[root@localhost ~]#chmod -R +x shell/*
​
[root@localhost ~]# ./shell/father.sh 
father.sh:NAME=father
fatther is PID=12053
son.sh:NAME=father
son.sh:NAME=son
son.sh PID is 12054
son.sh father pid is 12053
[root@localhost ~]# ./shell/father.sh 
father.sh:NAME=father
fatther is PID=12142
son.sh:NAME=father
son.sh:NAME=son
son.sh PID is 12143
son.sh father pid is 12142#父进程定义了一个环境变量,在子进程上可以进行调用#父进程无法使用子进程的变量#子进程自己定义了一个同名变量,就覆盖环境变量

显示所有环境变量:

[root@localhost ~]# env
[root@localhost ~]# printenv
[root@localhost ~]# export
[root@localhost ~]# declare -x

删除变量

[root@localhost ~]#unset shellname1 shellname2

Bash内建的环境变量

PATH
SHELL
USER
UID
PWD
SHLVL #shell的嵌套层数,即深度
LANG
MAIL
HOSTNAME
HISTSIZE
_      #下划线,表示前一命令的最后一个参数

6、只读变量

只读变量:只能声明定义,但后续不能修改和删除

声明只读变量:

readonly name
declare -r name

查看只读变量:

readonly [-p]
declare -r

}

7、位置与预定义变量

位置变量:在Bash Shell中内置的变量,在脚本代码中调用命令行传递给脚本的参数

$1,$2,... 对应第一个,第二个等参数,shift[n]换位置,最多9个
#预定义变量
$0  命令本身,包括路径
$*  传递给脚本的所有参数,全部参数合成一个字符串
$@  传递给脚本的所有参数,每个参数为独立字符串
$#  传递给脚本的参数的个数
$?  上个命令的退出状态,或函数的返回值
$$  当前shell进程ID。对于Shell脚本,就是这些脚本所在的进程ID
​
注意:$@,$*只有被双引号括起来的时候才会有差异

清空所有位置变量

set --
//写在脚本内部

实例演示1:

[root@localhost ~]# vim ARG.sh
#!/bin/bash
echo "1st arg is $1"
echo "2st arg is $2"
echo "3st arg is $3"
echo "4st arg is $4"
echo "The number of are is $#"
echo "All args are $*"
echo "All args are $@"
echo "The scriptname is `basename $0`"
[root@localhost ~]# chmod +x ARG.sh
[root@localhost ~]# ./ARG.sh {1..10}
1st arg is 1
2st arg is 2
3st arg is 3
4st arg is 4
The number of are is 10
All args are 1 2 3 4 5 6 7 8 9 10
All args are 1 2 3 4 5 6 7 8 9 10
The scriptname is ARG.sh
[root@localhost ~]# 

8、 退出状态码变量

进程执行后,将使用变量 ? 保存状态码的相关数字,不同的值反应成功与失败, ?保存状态码的相关数字,不同的值反应成功与失败, ?保存状态码的相关数字,不同的值反应成功与失败,的取值范围为[0,255]

$?的值为0 代表成功
$?的值不为0 代表失败

用户可以在脚本中使用以下命令自定义退出状态码

exit [n]

实例:

[root@localhost ~]# ping -c 2 www.baidu.com > /dev/null
[root@localhost ~]# echo $?
0
[root@localhost ~]# cmd
-bash: cmd: 未找到命令
[root@localhost ~]# echo $?
127
[root@localhost ~]# 

9、 展开命令行

9.1展开命令执行顺序
把命令行分成单个命令词
展开别名
展开大括号的声明{}
展开波浪符声明(~)
命令替换$()和``
再次把命令行分成命令词
展开文件通配(*,?,[abc]等)
准备I/O重导向(<,>)
运行命令
9.2 防止扩展
反斜线(\)会使随后的字符按原意解释

实例:

[root@localhost ~]# echo Your cost:\$5.00
Your cost:$5.00
[root@localhost ~]# 
9.3 加引号来防止扩展
单引号(' ')防止所有扩展
双引号(" ")可防止扩展,但是以下清空例外:$(美元符号)
9.4 变量扩展
``:反引号,命令替换
\:反斜线,禁止单个字符扩展
!:叹号,历史命令替换
http://www.xdnf.cn/news/1428355.html

相关文章:

  • @ZooKeeper 详细介绍部署与使用详细指南
  • 【JavaScript】前端两种路由模式,Hash路由,History 路由
  • 通过 FinalShell 访问服务器并运行 GUI 程序,提示 “Cannot connect to X server“ 的解决方法
  • NV115NV119美光固态闪存NV129NV112
  • 【53页PPT】华为制造行业数字化转型工业互联网智能制造解决方案(附下载方式)
  • Spring MVC BOOT 中体现的设计模式
  • Python 环境配置初学者指南:从安装到 Pycharm 项目配置
  • OpenHarmony HVB安全启动一键启停全栈实践:从U-Boot签名到fastboot解锁的闭环避坑指南
  • Python OpenCV图像处理与深度学习:Python OpenCV性能优化与高效图像处理
  • 为什么神经网络网络算法比机器学习模型算法更加强大?
  • 关于嵌入式学习——嵌入式硬件1
  • More Effective C++ 条款23:考虑使用其他程序库
  • 没有天硕工业级SSD固态硬盘,物联网痛点如何解决?
  • 虚实交互新突破:Three.js融合AR技术的孪生数据操控方法
  • Angular事件处理全攻略:从基础到进阶的完整指南
  • JSON Schema 格式详解、版本介绍和示例教程
  • 利用 Python 获取微店商品详情 API 接口数据的实战指南
  • 最新!阿里财报电话会蒋凡与吴泳铭透露重要信息:淘宝闪购成绩斐然;零售与AI双轮驱动;阿里云推出“Agent Bay”新产品···
  • 【学Python自动化】 8.1 Python 与 Rust 错误处理对比学习笔记
  • Spring Security资源服务器在高并发场景下的认证性能优化实践指南
  • 使用DataLoader加载本地数据
  • 深度学习——基于卷积神经网络实现食物图像分类(数据增强)
  • JVM1.8与1.9的区别是什么?
  • 【系统架构设计(11)】软件测试全景解析:从方法论到实践策略
  • 面试tips--JVM(4)--Minor GC Major GC Full GC
  • STL库——deque/priority_queue
  • 【爬油管搜索视频软件】youtube爬虫工具,根据关键词采集搜到的视频数据
  • 数据分析与挖掘工程师学习规划
  • React学习教程,从入门到精通, React 入门指南:React JSX 语法知识点详解及案例代码(8)
  • 工业界实战之数据存储格式与精度