Shell 脚本语法规则速查手册

Shell 脚本语法规则速查手册 Shell 脚本语法规则速查手册适用于 Bash / Shell 脚本编写Linux 环境一、文件基础规则1.1 文件扩展名与权限# 推荐扩展名 .sh 不是必须但便于识别myscript.sh# 给脚本加执行权限只需一次之后可以 ./运行chmodx myscript.sh# 运行方式./myscript.sh# 方式一直接运行需要执行权限 Shebangbashmyscript.sh# 方式二指定解释器运行不需要执行权限1.2 第一行必须写 Shebang必写#!/bin/bash # ✅ 推荐用 Bash 解释器功能最全#!/bin/sh # ✅ 可用用 POSIX Shell兼容性好功能少#!/usr/bin/env bash # ✅ 可用自动找系统里的 bash跨平台推荐# ❌ 错误Shebang 不能写在第2行及以后# 第1行空了#!/bin/bash # ← 这样写无效二、注释规则# 这是一行注释# 后面的内容全被忽略echohello# 这是行尾注释# 前面是代码后面是说明# Shell 没有多行注释想注释多行就每行都写 ## 第一行注释# 第二行注释# 第三行注释# ❌ 不要用这些Shell 不认/* 这样的多行注释 Shell 会报错 */ // 双斜线也不是注释三、最容易踩的坑必背坑点正确写法错误写法报错信息两边不能有空格nametomname tomname: command not found[ ]两边必须有空格if [ -f a.txt ]if [-f a.txt][-f: command not found取变量值要加$echo $nameecho name直接输出字母 name每个if必须有fi配对if ... then ... fi漏写fisyntax error: unexpected end of file理解$的本质$可以近似理解为 C 语言 / C 里的解引用*本质上就是变量展开——解析脚本时Shell 会把$变量名替换成变量里存的值。但要注意Shell 脚本里没有内存和指针的概念$只是单纯的文本替换不是去访问某个内存地址。四、变量4.1 定义与取值# 定义变量等号两边绝对不能有空格name小明age18ip127.0.0.1# 取值加 $ 符号echo$name# 输出小明echo${name}# 等价写法推荐用这个更清晰# 错误示例注意空格name小明# ❌ 等号两边有空格 灾难4.2 双引号 vs 单引号city北京# 双引号里面的变量会被替换解析 $echo我住在$city# 输出我住在 北京# 单引号原样输出不会解析 $echo我住在 $city# 输出我住在 $city# 推荐用变量的地方都加双引号防空格filemy photo.jpgrm$file# ✅ 正确能识别空格rm$file# ❌ 危险会当成 rm my 和 photo.jpg 两个文件4.3 常用内置变量变量含义示例值$0脚本本身的文件名./ser_start.sh$1$2$3第1/2/3个命令行参数./s.sh a b→$1a, $2b$#参数的个数./s.sh a b→2$所有参数数组形式所有参数列表$$当前脚本的进程ID12345$?上一条命令的返回值0成功非0失败0或1$(pwd)或\pwd取命令的执行结果/home/user/project五、条件判断if / else5.1 基本语法if[条件]then# 条件成立时执行elif[条件2]then# 条件2成立时执行else# 都不成立时执行fi# ← 不能漏fi 是 if 反过来写5.2 常用判断条件文件判断if[-fservice.conf]# 文件存在且是普通文件if[-doutput]# 目录存在if[-xservice]# 文件有执行权限if[-sa.txt]# 文件存在且大小 0if[!-fa.txt]# 文件不存在! 取反数值比较写法含义示例-eq等于 equalif [ $a -eq 10 ]-ne不等于 not equalif [ $a -ne 10 ]-gt大于 greater thanif [ $a -gt 5 ]-lt小于 less thanif [ $a -lt 5 ]-ge大于等于if [ $a -ge 10 ]-le小于等于if [ $a -le 10 ]# 示例判断数值age18if[$age-ge18]thenecho成年人fi字符串比较if[$a$b]# 字符串相等 两边有空格if[$a!$b]# 字符串不相等if[-z$a]# 字符串为空长度为0if[-n$a]# 字符串不为空# 示例name小明if[$name小明]thenecho你好小明fi逻辑运算if[$a-gt5][$a-lt20]# 并且两个都真才真if[$a-lt5]||[$a-gt20]# || 或者一个真就真六、循环6.1 for 循环# 遍历列表foriin12345doecho数字$idone# 遍历文件forfilein*.cppdoecho找到C文件$filedone# C 语言风格需要 bashfor((i0;i10;i))doecho$idone6.2 while 循环n1while[$n-le5]doecho第$n次n$((n1))# 变量自增done七、函数# 定义函数greet(){echo你好$1# $1 函数的第一个参数}# 调用函数不需要括号greet小明# 输出你好小明greet小红# 输出你好小红# 带返回值的函数返回值只能是 0-255 的数字add(){sum$(($1$2))return$sum# 只能返回数字}add35echo结果$?# 用 $? 取返回值8函数参数怎么传Shell 定义函数时括号里不用写形参greet()括号是空的调用函数时在函数名后面直接写实参即可函数内部通过$1、$2这类特殊变量拿到第 1、2 个参数和脚本接收命令行参数是同一套机制。八、数组# 定义数组arr(applebananacherry)# 取值echo${arr[0]}# 第1个appleecho${arr[1]}# 第2个bananaecho${arr[]}# 全部元素apple banana cherryecho${#arr[]}# 长度3# 遍历数组forfruitin${arr[]}doecho水果$fruitdone九、输入输出9.1 输出 echoecho普通文本echo-e这里会\t转义\n特殊字符# -e 启用转义\t 制表 \n 换行echo-n不换行输出# -n 输出后不自动换行9.2 输入 readecho请输入你的名字readusernameecho你好$username# -p 可以直接加提示read-p请输入端口portecho端口号是$port9.3 重定向# 把输出写入文件覆盖写echohelloa.txt# 追加写入不覆盖echoworlda.txt# 错误输出一起重定向make1log.txt2err.txt# 1标准输出 2错误输出makelog.txt21# 错误也写到同一个文件十、常用命令写法速查需求写法取命令结果today$(date)或today\date数字运算sum$(( a b ))切换到脚本所在目录cd $(dirname $0)判断命令是否执行成功if make; then echo ok; fi上一条命令失败就退出set -e脚本第二行加一次即可未定义的变量报错set -u防拼写错误一行写多条命令make clean make前一个成功才执行后一个一行写多条命令make clean; make不管成功与否都执行后台运行./service 暂停/休眠sleep 3休眠3秒十一、脚本推荐模板直接抄用#!/bin/bashset-e# 遇到错误立即退出避免错误扩散# set -u # 用到未定义的变量时报错调试阶段建议打开# # 函数区# log_info(){echo[INFO]$1}log_error(){echo[ERROR]$1}# # 主逻辑# # 切换到脚本所在目录SCRIPT_DIR$(cd $(dirname$0)pwd) cd $SCRIPT_DIR log_info 脚本开始运行... # 你的代码写在这里 log_info 脚本运行完成 ✓十二、常见报错与解决报错信息原因解决Permission denied没有执行权限chmod x xxx.shbad interpreterShebang 写错或第一行不是它第一行写#!/bin/bashcommand not found两边加空格了 / 命令拼错了namea不要空格syntax errorif漏了fi/for漏了done检查配对的结束关键字unary operator expected[里变量为空没加引号[ $a x ]加双引号too many arguments变量值里有空格没加引号所有变量取值都加$var[: missing ]]前面没空格[ -f a.txt ]注意空格