shell脚本语法详解
目录
shell语法基础
指定shell解析器
注释
运行
变量
定义变量
引用变量
清除变量值
从键盘获取值
输入单值
添加输入提示语
读取多值
编辑
定义只读变量
环境变量
设置环境变量与查看环境变量
特殊变量
三种引号的作用与区别
小括号与大括号
参数传递
位置参数传递
选项参数传递
获取参数相关信息
其余预设变量
字符串处理
条件测试
文件测试
字符串测试
数值测试
控制语句
逻辑语句
条件语句
if语句
case语句
循环语句
for循环
while循环
函数
函数定义
函数的调用与返回
文件导入
shell语法基础
指定shell解析器
#!/bin/bash
#!用来声明脚本由什么shell解释,否则使用默认shell
shell终端有多种,我们大部分用的是sh或者bash,其中sh是最原始的shell,而bash不完全兼容sh,查看系统可用的shell终端可用以下命令
vim /etc/shells
/bin/sh
/bin/bash
/bin/rbash
/bin/dash
/usr/bin/tmux
/usr/bin/screen
注释
#
运行
shell脚本有三种执行方式
- ./xxx.sh
- ./xxx.sh :先按照 文件中#!指定的解析器解析
如果#!指定指定的解析器不存在 才会使用系统默认的解析器
- bash xxx.sh
- bash xxx.sh:指明先用bash解析器解析
如果bash不存在 才会使用默认解析器
- . xxx.sh
- 直接使用默认解析器解析(不会执行第一行的#!指定的解析器)但是第一行还是要写的
三种执行情况:
打开终端就会有以后个解释器,我们称为当前解释器
我们指定解析器的时候(使用 ./xxx.sh 或 bash xxx.sh)时会创建一个子shell解析 脚本
变量
定义变量
变量名=变量值
如:num=10
引用变量
$变量名
清除变量值
unset
从键盘获取值
read命令可以从键盘获取值
输入单值
#!/bin/bash
echo "--------"
read data
echo "data=$data"
运行结果
添加输入提示语
使用read命令的-p选项可以添加输入提示语
#!/bin/bash
echo "--------"
read -p "please input the value of data:" data
echo "data=$data"
读取多值
#!/bin/bash
read -p "please input the value of data1 and data2 >>> " data1 data2
echo "data1 is ${data1} and the data2 is ${data2}"
注意,输入时以空格作为分隔符,运行结果如下:
定义只读变量
readonly关键字可标识一个变量为只读变量
#!/bin/bash
readonly num=10
echo "num=$num"
num=20
echo "after num=$num"
环境变量
设置环境变量与查看环境变量
创建一个test.sh脚本,并写下
#!/bin/bash
export MY_DATA=42
退出保存,然后在终端中输入
source ./test.sh
然后在终端中输入
上述过程解析
- export关键字用于定义一个环境变量
- source命令用于将脚本中的环境变量生效,生效后的作用就是让其他脚本可识别该变量
- 因此,假如我们重新定义一个新的脚本,输入echo MY_DATA,是可以输出该值的
- env命令用于列出所有的环境变量
特殊变量
三种引号的作用与区别
- 双引号:可以解析变量的值
- 单引号:不能解析变量的值,直接将单引号中的内容作为字符串处理
- 反引号(数字键1前的按键):引用系统命令
#!/bin/bash
num=42
echo "num=$num"
echo 'num=$num'#直接将$num作为字符串处理。并不会解析num的值echo "date is `date`"
上述代码的运行结果如下所示
小括号与大括号
- ():由子shell完成,不会影响当前shell的值
- {}:由当前shell完成,通常用于作为变量引用的边界
#!/bin/bash
data=42
(
#以下内容由子shell完成,不会影响外边data的值
data=43
echo "内部data值为:$data"
)echo "外部data值为:$data"
#使用{}将data变量的引用与外部的eee三个字符区分开
echo "${data}eee"
echo ">>>>>>>"
echo "$dataeee"
运行结果
因此,一个好的习惯应当是,在引用变量的时候,使用{}将其包裹
参数传递
位置参数传递
shell中用$1、$2、$3来传递外部的第一个参数、第二个参数、第三个参数等等,该参数传递方式称为位置参数传递
创建一个test.sh脚本,内容定义如下
#!/bin/bash
echo "第一个参数值:$1"
echo "第二个参数值:$2"
echo "第三个参数值:$3"
保存退出,在命令行中执行脚本,并传递参数
./test.sh 42 43 45
运行结果为
选项参数传递
如果想实现选项参数传递,而不依赖于位置,可参考
shell脚本实现长短项参数设置_shell脚本处理长参数-CSDN博客
获取参数相关信息
- $#:获取传入的参数个数
- $@:获取所有的参数内容,其中每个参数都会作为独立的字符串处理,假设输入参数是
one two three
,使用"$@"
会得到"one"
、"two"
、"three"
三个独立的参数。- $*:获取所有的参数内容,并将所有参数作为一个整体处理。输入参数
one two three
,使用"$*"
会得到"one two three"
,成为一个单一字符串。
#!/bin/bash
echo "第一个参数值:$1"
echo "第二个参数值:$2"
echo "第三个参数值:$3"
echo "the number of all parms is: $#"
echo "all parms value is: $@"
echo "all parms value is: $*"for parm in "$@"; doecho "${parm}"
donefor parm in "$*"; doecho "${parm}"
done
运行结果
其余预设变量
- $?:获取命令执行后返回的状态,0表示执行成功,无错误,非0表示执行失败,有错误
- $0:获取当前执行的进程名
- $$:获取当前执行的进程号
代码实例
#!/bin/bash
function func1(){
#返回非0状态,表示func1函数执行出错return 1
}function func2(){
#获取传递给func2的参数parm1=$1parm2=$2echo "parm1 is ${parm} and the parm2 is ${pamr2}"#返回0,表示func2函数执行无误return_value="yes"echo ${return_value}return 0
}func1
echo "func1 return status is $?"func2 42 43
echo "func2 return status is $?"return_value=$(func2 54 56)
echo "func2 return status is $? ,and the return value is $return_value"
上述代码解析:
- function关键字用于定义一个函数
- shell中的return关键字是返回函数执行状态的,return后的值只能是数字,不能是其余字符串信息
- 如果想返回函数体内的值给函数外部执行者,使用echo命令
- shell中函数参数的传递,同样也使用上述的位置参数传递
执行结果
获取进程名与进程号
#!/bin/bash
echo "process name is $0"
echo "process number is $$"
字符串处理
#!/bin/bash
str="hello hello world"#获取
echo "字符串长度:${#str}"#从下标为3的字符开始截取子串
echo "${str:3}"#从下标为3的字符开始截取长度为4的子串
echo "${str:3:4}"#将字符串中的第一个hello替换为hahaha
new_str="${str/hello/hahaha}"
echo "$new_str"#将字符串中的所有hello替换为hhhhh
new_str1="${str//hello/hhhhh}"
echo "$new_str1"
条件测试
条件测试使用[ condition ]判断condition是否为真
使用方括号时,要注意在条件两边加上空格,同时,运算符和操作数之间必须有空格。缺少空格会导致语法错误。
文件测试
判断文件状态
- -e:判断文件是否存在
- -d:判断文件是否是一个目录
- -f:判断文件是否是一个文件
- -s:判断文件是否非空
- -r:判断文件是否可读
- -w:判断文件是否可写
- -x:判断文件是否可执行
- -L:判断该文件是否是符号链接
- -c:判断是否是字符设备
- -b:判断是否是块设备
#!/bin/bashfor item in `ls`; doif [ -d "$item" ]; thenecho "$item 是一个目录"elif [ -f "$item" ]; thenecho "$item 是一个普通文件"elseecho "$item 是其他类型"fi
done
字符串测试
- =:判断两个字符串是否相等
- !=:判断两个字符串是否不相等
- -z:判断是否是空串
- -n:判断是否是非空串
#!/bin/bashread -p "str1=" str1
read -p "str2=" str2#如果str1和str2都不为空
if [[ ! -z ${str1} && ! -z ${str2} ]];thenecho "$str1"echo "$str2"
#如果str1和str2的值相等if [ "$str1" = "$str2" ]; thenecho "str1 equal str2"elseecho "str1 not equal str2"fi
fi
数值测试
#!/bin/bashread -p "num1=" num1
read -p "num2=" num2if [ $num1 -eq $num2 ]; thenecho "$num1 equal $num2"
elif [ $num1 -gt $num2 ];thenecho "$num1 greater than $num2"
elseecho "$num1 less than $num2 "
fi
控制语句
逻辑语句
- 与运算:&&
- 或运算:||
- 非运算:!
条件语句
if语句
使用格式如下:
if [条件1]; then执行第一段程序
elif [条件2];then
执行第二段程序
else执行第三段程序
fi
结合上述字符串测试与数值测试案例学习即可
case语句
#!/bin/bashread -p "please input choice yes or no >>> " choicecase $choice inyes | y* | Y*)echo "yes";;no | n* | N*)echo "no";;*)echo "others";;
esac
循环语句
for循环
#!/bin/bashread -p "please input n is >>> " n
declare -i sum=0
declare -i i=0
for ((i=0;i<n;i++))
dosum=$sum+$i
doneecho "sum=$sum"
for item in `ls`; doif [ -d "$item" ]; thenecho "$item 是一个目录"elif [ -f "$item" ]; thenecho "$item 是一个普通文件"elseecho "$item 是其他类型"fi
done
while循环
#!/bin/bashread -p "请输入一个正整数: " nwhile [ $n -gt 0 ]
doecho "当前数字是: $n"n=$((n - 1))
doneecho "循环结束!"
函数
函数定义
function 函数名(){函数体
}
函数的调用与返回
函数的调用和平时调用命令一样
写一个test.sh脚本,并定义文件内容如下:
#!/bin/bash
function max(){if [ $1 -gt $2 ];thenecho $1elseecho $2fi
}max_val=$(max $@)
echo "max num is $max_val"
然后在终端命令行输入
./test.sh 12 45
执行结果如下所示
文件导入
定义一个max.sh文件
#!/bin/bash
function Max(){if [ $1 -gt $2 ];thenecho $1elseecho $2fi
}
然后再定义一个main.sh文件
#!/bin/bash
#导入max.sh文件
source max.shread -p "num1=" num1
read -p "num2=" num2
#使用max.sh文件中的Max函数
max_val=$(Max $num1 $num2)
echo "max_val is $max_val"
终端命令行执行
参考
shell脚本语言(超全超详细) - 知乎
相关文章:

shell脚本语法详解
目录 shell语法基础 指定shell解析器 注释 运行 变量 定义变量 引用变量 清除变量值 从键盘获取值 输入单值 添加输入提示语 读取多值 编辑 定义只读变量 环境变量 设置环境变量与查看环境变量 特殊变量 三种引号的作用与区别 小括号与大括号 参数传递 位…...

2021亚洲机器学习会议:面向单阶段跨域检测的域自适应YOLO(ACML2021)
原文标题:Domain Adaptive YOLO for One-Stage Cross-Domain Detection 中文标题:面向单阶段跨域检测的域自适应YOLO 1、Abstract 域转移是目标检测器在实际应用中推广的主要挑战。两级检测器的域自适应新兴技术有助于解决这个问题。然而,两级…...
面试题:描述在前端开发中,如何利用数据结构来优化页面渲染性能,并给出一个具体的示例。
在前端开发中,优化页面渲染性能是提升用户体验的关键之一。合理地使用数据结构可以有效地减少DOM操作的次数、提高数据处理的效率,从而加快页面的渲染速度。以下是一些策略,并给出一个具体的示例。 1. 使用合适的数据结构 数组与对象&#…...

微积分复习笔记 Calculus Volume 1 - 3.2 he Derivative as a Function
3.2 The Derivative as a Function - Calculus Volume 1 | OpenStax...

html 轮播图效果
轮播效果: 1、鼠标没有移入到banner,自动轮播 2、鼠标移入:取消自动轮播、移除开始自动轮播 3、点击指示点开始轮播到对应位置 4、点击前一个后一个按钮,轮播到上一个下一个图片 注意 最后一个图片无缝滚动,就是先克隆第一个图片…...
Android Room(SQLite) too many SQL variables异常
SQLiteException 一、解决办法1. 修改数据库语句2. 分批执行 二、问题根源 转载请注明出处: https://blog.csdn.net/hx7013/article/details/143198862 在使用 Room 或其他基于 SQLite 的 ORM 框架时,批量操作如 IN 或 NOT IN 查询可能会触发 android.database.sqli…...

sentinel原理源码分析系列(八)-熔断
限流为了防止过度使用资源造成系统不稳,熔断是为了识别出”坏”资源,避免好的资源受牵连(雪崩效应),是保证系统稳定性的关键,也是资源有效使用的关键,sentinel熔断插槽名称Degrade(降级),本人觉得应该改为熔…...
安全见闻(4)——开阔眼界,不做井底之蛙
内容预览 ≧∀≦ゞ 安全见闻四:操作系统安全机制深度解析声明操作系统机制1. 注册表2. 防火墙3. 自启动与计划任务4. 事件日志5. 内核驱动与设备驱动6. 系统服务7. 进程与线程8. 系统编程 从操作系统机制看病毒设计1. 自启动:病毒如何在系统启动时运行&a…...

(二十二)、k8s 中的关键概念
文章目录 1、总体概览2、第一层:物理机、集群、Node、Pod 之间的关系2、第二层:命名空间 Namespace3、定义4、控制平面(Control Plane)5、特别的概念 Service6、Deployment 经过 之前几篇文章对 k8s 的实践,结合实践&…...

python基础综合案例(数据可视化-地图可视化)
1.基础地图使用 注意写名字的时候要写全名,比如上海市不能写出上海,不然看不到数据 鼠标点击即可看到数据 设置属性的时候不要忘记导包 # 演示地图可视化的基础使用 from pyecharts.charts import Map from pyecharts.options import VisualMapOpts # 准…...

基于SpringBoot足球场在线预约系统的设计与实现
💗博主介绍💗:✌在职Java研发工程师、专注于程序设计、源码分享、技术交流、专注于Java技术领域和毕业设计✌ 温馨提示:文末有 CSDN 平台官方提供的老师 Wechat / QQ 名片 :) Java精品实战案例《700套》 2025最新毕业设计选题推荐…...

操作系统笔记(二)进程,系统调用,I/O设备
什么是进程? 一个正在执行的程序一个包含运行一个程序所需要的所有信息的容器进程的信息保存在一个进程表中( Process Table)。进程表中的每一项对应一个进程,称为进程控制块(Process control block,PCB)。 PCB信息包括: 用户ID(UID)、进程ID(PID)…...

DevOps实践:在GitLab CI/CD中集成静态分析Helix QAC的工作原理与优势
基于云的GitLab CI/CD平台使开发团队能够简化其CI/CD流程,并加速软件开发生命周期(SDLC)。 将严格的、基于合规性的静态分析(如Helix QAC所提供)作为新阶段添加到现有的GitLab CI/CD流程中,将进一步增强SD…...
前端面试题-token的登录流程、JWT
这是我的前端面试题的合集的第一篇,后面也会更新一些笔试题目。秋招很难,也快要结束了。但是,不要放弃,一起加油^_^ 一、token的登录流程 1.客户端用账号密码请求登录 2.服务端收到请求,需要去验证账号密码 3.验证成…...

【软考高级架构】关于分布式数据库缓存redis的知识要点汇总
一.分布式数据库的含义 分布式数据库缓存指的是在高并发的环境下,为了减轻数据库的压力和提高系统响应时间,在数据库系统和应用系统之间增加一个独立缓存系统。 二.常见的缓存技术 (1)MemCache: Memcache是一个高性能的分布式的内…...

构建自然灾害预警决策一体化平台,筑牢工程安全数字防线
近年来,国家和部委也强调了要切实加强地质灾害监测预警。作为国内智慧应急领域的先行者,Mapmost持续探索利用数字孪生技术,推进自然灾害风险预警精细化,强化对监测数据的综合分析和异常信息研判处置。建立健全区域风险预警与隐患点…...

随机题两题
逆序对 题目 给定一个数组,求其中有多少逆序对,要求时间复杂度不超过nlogn。 思路 使用归并排序的分治思想,将数组递归地分为左右两部分。在合并两个有序子数组时,若左侧数组中的某个数大于右侧数组中的某个数,则可…...

信息安全工程师(69)数字水印技术与应用
前言 数字水印技术是一种在数字媒体中嵌入特定信息的技术,这些信息可以是版权信息、元数据等。 一、数字水印技术的定义与原理 数字水印技术(Digital Watermarking)是将一些标识信息(即数字水印)直接嵌入数字载体&…...

知识点框架笔记3.0笔记
如果基础太差,搞不清基本交规的(模考做不到60分),建议找肖肖或者小轩老师的课程看一遍,内容差不多(上面有链接),笔记是基于肖肖和小轩老师的科目一课程以及公安部交管局法规…...
Android组件化开发
Android组件化开发 组件化开发概念组件化开发的由来组件化开发有什么优势?组件化开发如何拿到入口参数?如何解决相同资源文件名合并的冲突?模式切换,如何使APP在单独调试跟整体调试自由切换?多个Module之间如何引用一些共同的library以及工具类?我们如何实现依赖关系及组…...

多云管理“拦路虎”:深入解析网络互联、身份同步与成本可视化的技术复杂度
一、引言:多云环境的技术复杂性本质 企业采用多云策略已从技术选型升维至生存刚需。当业务系统分散部署在多个云平台时,基础设施的技术债呈现指数级积累。网络连接、身份认证、成本管理这三大核心挑战相互嵌套:跨云网络构建数据…...
谷歌浏览器插件
项目中有时候会用到插件 sync-cookie-extension1.0.0:开发环境同步测试 cookie 至 localhost,便于本地请求服务携带 cookie 参考地址:https://juejin.cn/post/7139354571712757767 里面有源码下载下来,加在到扩展即可使用FeHelp…...
CVPR 2025 MIMO: 支持视觉指代和像素grounding 的医学视觉语言模型
CVPR 2025 | MIMO:支持视觉指代和像素对齐的医学视觉语言模型 论文信息 标题:MIMO: A medical vision language model with visual referring multimodal input and pixel grounding multimodal output作者:Yanyuan Chen, Dexuan Xu, Yu Hu…...

【大模型RAG】Docker 一键部署 Milvus 完整攻略
本文概要 Milvus 2.5 Stand-alone 版可通过 Docker 在几分钟内完成安装;只需暴露 19530(gRPC)与 9091(HTTP/WebUI)两个端口,即可让本地电脑通过 PyMilvus 或浏览器访问远程 Linux 服务器上的 Milvus。下面…...
Python爬虫(二):爬虫完整流程
爬虫完整流程详解(7大核心步骤实战技巧) 一、爬虫完整工作流程 以下是爬虫开发的完整流程,我将结合具体技术点和实战经验展开说明: 1. 目标分析与前期准备 网站技术分析: 使用浏览器开发者工具(F12&…...

让AI看见世界:MCP协议与服务器的工作原理
让AI看见世界:MCP协议与服务器的工作原理 MCP(Model Context Protocol)是一种创新的通信协议,旨在让大型语言模型能够安全、高效地与外部资源进行交互。在AI技术快速发展的今天,MCP正成为连接AI与现实世界的重要桥梁。…...

用docker来安装部署freeswitch记录
今天刚才测试一个callcenter的项目,所以尝试安装freeswitch 1、使用轩辕镜像 - 中国开发者首选的专业 Docker 镜像加速服务平台 编辑下面/etc/docker/daemon.json文件为 {"registry-mirrors": ["https://docker.xuanyuan.me"] }同时可以进入轩…...
Android Bitmap治理全解析:从加载优化到泄漏防控的全生命周期管理
引言 Bitmap(位图)是Android应用内存占用的“头号杀手”。一张1080P(1920x1080)的图片以ARGB_8888格式加载时,内存占用高达8MB(192010804字节)。据统计,超过60%的应用OOM崩溃与Bitm…...
Swagger和OpenApi的前世今生
Swagger与OpenAPI的关系演进是API标准化进程中的重要篇章,二者共同塑造了现代RESTful API的开发范式。 本期就扒一扒其技术演进的关键节点与核心逻辑: 🔄 一、起源与初创期:Swagger的诞生(2010-2014) 核心…...
AspectJ 在 Android 中的完整使用指南
一、环境配置(Gradle 7.0 适配) 1. 项目级 build.gradle // 注意:沪江插件已停更,推荐官方兼容方案 buildscript {dependencies {classpath org.aspectj:aspectjtools:1.9.9.1 // AspectJ 工具} } 2. 模块级 build.gradle plu…...