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

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)

原文标题&#xff1a;Domain Adaptive YOLO for One-Stage Cross-Domain Detection 中文标题&#xff1a;面向单阶段跨域检测的域自适应YOLO 1、Abstract 域转移是目标检测器在实际应用中推广的主要挑战。两级检测器的域自适应新兴技术有助于解决这个问题。然而&#xff0c;两级…...

面试题:描述在前端开发中,如何利用数据结构来优化页面渲染性能,并给出一个具体的示例。

在前端开发中&#xff0c;优化页面渲染性能是提升用户体验的关键之一。合理地使用数据结构可以有效地减少DOM操作的次数、提高数据处理的效率&#xff0c;从而加快页面的渲染速度。以下是一些策略&#xff0c;并给出一个具体的示例。 1. 使用合适的数据结构 数组与对象&#…...

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

3.2 The Derivative as a Function - Calculus Volume 1 | OpenStax...

html 轮播图效果

轮播效果&#xff1a; 1、鼠标没有移入到banner,自动轮播 2、鼠标移入&#xff1a;取消自动轮播、移除开始自动轮播 3、点击指示点开始轮播到对应位置 4、点击前一个后一个按钮&#xff0c;轮播到上一个下一个图片 注意 最后一个图片无缝滚动&#xff0c;就是先克隆第一个图片…...

Android Room(SQLite) too many SQL variables异常

SQLiteException 一、解决办法1. 修改数据库语句2. 分批执行 二、问题根源 转载请注明出处: https://blog.csdn.net/hx7013/article/details/143198862 在使用 Room 或其他基于 SQLite 的 ORM 框架时&#xff0c;批量操作如 IN 或 NOT IN 查询可能会触发 android.database.sqli…...

sentinel原理源码分析系列(八)-熔断

限流为了防止过度使用资源造成系统不稳&#xff0c;熔断是为了识别出”坏”资源&#xff0c;避免好的资源受牵连(雪崩效应)&#xff0c;是保证系统稳定性的关键&#xff0c;也是资源有效使用的关键&#xff0c;sentinel熔断插槽名称Degrade(降级)&#xff0c;本人觉得应该改为熔…...

安全见闻(4)——开阔眼界,不做井底之蛙

内容预览 ≧∀≦ゞ 安全见闻四&#xff1a;操作系统安全机制深度解析声明操作系统机制1. 注册表2. 防火墙3. 自启动与计划任务4. 事件日志5. 内核驱动与设备驱动6. 系统服务7. 进程与线程8. 系统编程 从操作系统机制看病毒设计1. 自启动&#xff1a;病毒如何在系统启动时运行&a…...

(二十二)、k8s 中的关键概念

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

python基础综合案例(数据可视化-地图可视化)

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

基于SpringBoot足球场在线预约系统的设计与实现

&#x1f497;博主介绍&#x1f497;&#xff1a;✌在职Java研发工程师、专注于程序设计、源码分享、技术交流、专注于Java技术领域和毕业设计✌ 温馨提示&#xff1a;文末有 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流程&#xff0c;并加速软件开发生命周期&#xff08;SDLC&#xff09;。 将严格的、基于合规性的静态分析&#xff08;如Helix QAC所提供&#xff09;作为新阶段添加到现有的GitLab CI/CD流程中&#xff0c;将进一步增强SD…...

前端面试题-token的登录流程、JWT

这是我的前端面试题的合集的第一篇&#xff0c;后面也会更新一些笔试题目。秋招很难&#xff0c;也快要结束了。但是&#xff0c;不要放弃&#xff0c;一起加油^_^ 一、token的登录流程 1.客户端用账号密码请求登录 2.服务端收到请求&#xff0c;需要去验证账号密码 3.验证成…...

【软考高级架构】关于分布式数据库缓存redis的知识要点汇总

一.分布式数据库的含义 分布式数据库缓存指的是在高并发的环境下&#xff0c;为了减轻数据库的压力和提高系统响应时间&#xff0c;在数据库系统和应用系统之间增加一个独立缓存系统。 二.常见的缓存技术 &#xff08;1&#xff09;MemCache: Memcache是一个高性能的分布式的内…...

构建自然灾害预警决策一体化平台,筑牢工程安全数字防线

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

随机题两题

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

信息安全工程师(69)数字水印技术与应用

前言 数字水印技术是一种在数字媒体中嵌入特定信息的技术&#xff0c;这些信息可以是版权信息、元数据等。 一、数字水印技术的定义与原理 数字水印技术&#xff08;Digital Watermarking&#xff09;是将一些标识信息&#xff08;即数字水印&#xff09;直接嵌入数字载体&…...

知识点框架笔记3.0笔记

如果基础太差&#xff0c;搞不清基本交规的&#xff08;模考做不到60分&#xff09;&#xff0c;建议找肖肖或者小轩老师的课程看一遍&#xff0c;内容差不多&#xff08;上面有链接&#xff09;&#xff0c;笔记是基于肖肖和小轩老师的科目一课程以及公安部交管局法规&#xf…...

Android组件化开发

Android组件化开发 组件化开发概念组件化开发的由来组件化开发有什么优势?组件化开发如何拿到入口参数?如何解决相同资源文件名合并的冲突?模式切换,如何使APP在单独调试跟整体调试自由切换?多个Module之间如何引用一些共同的library以及工具类?我们如何实现依赖关系及组…...

华为云AI开发平台ModelArts

华为云ModelArts&#xff1a;重塑AI开发流程的“智能引擎”与“创新加速器”&#xff01; 在人工智能浪潮席卷全球的2025年&#xff0c;企业拥抱AI的意愿空前高涨&#xff0c;但技术门槛高、流程复杂、资源投入巨大的现实&#xff0c;却让许多创新构想止步于实验室。数据科学家…...

业务系统对接大模型的基础方案:架构设计与关键步骤

业务系统对接大模型&#xff1a;架构设计与关键步骤 在当今数字化转型的浪潮中&#xff0c;大语言模型&#xff08;LLM&#xff09;已成为企业提升业务效率和创新能力的关键技术之一。将大模型集成到业务系统中&#xff0c;不仅可以优化用户体验&#xff0c;还能为业务决策提供…...

Day131 | 灵神 | 回溯算法 | 子集型 子集

Day131 | 灵神 | 回溯算法 | 子集型 子集 78.子集 78. 子集 - 力扣&#xff08;LeetCode&#xff09; 思路&#xff1a; 笔者写过很多次这道题了&#xff0c;不想写题解了&#xff0c;大家看灵神讲解吧 回溯算法套路①子集型回溯【基础算法精讲 14】_哔哩哔哩_bilibili 完…...

如何在看板中体现优先级变化

在看板中有效体现优先级变化的关键措施包括&#xff1a;采用颜色或标签标识优先级、设置任务排序规则、使用独立的优先级列或泳道、结合自动化规则同步优先级变化、建立定期的优先级审查流程。其中&#xff0c;设置任务排序规则尤其重要&#xff0c;因为它让看板视觉上直观地体…...

(二)TensorRT-LLM | 模型导出(v0.20.0rc3)

0. 概述 上一节 对安装和使用有个基本介绍。根据这个 issue 的描述&#xff0c;后续 TensorRT-LLM 团队可能更专注于更新和维护 pytorch backend。但 tensorrt backend 作为先前一直开发的工作&#xff0c;其中包含了大量可以学习的地方。本文主要看看它导出模型的部分&#x…...

CentOS下的分布式内存计算Spark环境部署

一、Spark 核心架构与应用场景 1.1 分布式计算引擎的核心优势 Spark 是基于内存的分布式计算框架&#xff0c;相比 MapReduce 具有以下核心优势&#xff1a; 内存计算&#xff1a;数据可常驻内存&#xff0c;迭代计算性能提升 10-100 倍&#xff08;文档段落&#xff1a;3-79…...

【Go】3、Go语言进阶与依赖管理

前言 本系列文章参考自稀土掘金上的 【字节内部课】公开课&#xff0c;做自我学习总结整理。 Go语言并发编程 Go语言原生支持并发编程&#xff0c;它的核心机制是 Goroutine 协程、Channel 通道&#xff0c;并基于CSP&#xff08;Communicating Sequential Processes&#xff0…...

第一篇:Agent2Agent (A2A) 协议——协作式人工智能的黎明

AI 领域的快速发展正在催生一个新时代&#xff0c;智能代理&#xff08;agents&#xff09;不再是孤立的个体&#xff0c;而是能够像一个数字团队一样协作。然而&#xff0c;当前 AI 生态系统的碎片化阻碍了这一愿景的实现&#xff0c;导致了“AI 巴别塔问题”——不同代理之间…...

【git】把本地更改提交远程新分支feature_g

创建并切换新分支 git checkout -b feature_g 添加并提交更改 git add . git commit -m “实现图片上传功能” 推送到远程 git push -u origin feature_g...

Pinocchio 库详解及其在足式机器人上的应用

Pinocchio 库详解及其在足式机器人上的应用 Pinocchio (Pinocchio is not only a nose) 是一个开源的 C 库&#xff0c;专门用于快速计算机器人模型的正向运动学、逆向运动学、雅可比矩阵、动力学和动力学导数。它主要关注效率和准确性&#xff0c;并提供了一个通用的框架&…...