千家信息网

Linux Bash语法总结

发表于:2026-11-04 作者:千家信息网编辑
千家信息网最后更新 2026年11月04日,在学习Linux的过程中,无可避免的会碰到一个既让人喜欢、又令人十分头疼的神奇的东西--bash编程,也就是shell脚本。那么什么是shell脚本呢?shell是一个命令语言解释器,而shell脚本
千家信息网最后更新 2026年11月04日Linux Bash语法总结

在学习Linux的过程中,无可避免的会碰到一个既让人喜欢、又令人十分头疼的神奇的东西--bash编程,也就是shell脚本。那么什么是shell脚本呢?shell是一个命令语言解释器,而shell脚本则是Linux命令的集合,按照预设的顺序依次解释执行,来完成特定的、较复杂的系统管理任务,类似于windows中的批处理文件。本篇博文主要介绍bash编程的基础语法讲解。

一、bash编程之变量

1)bash变量类别

本地变量:只对当前shelll进程有效的变量,对其他shell进程无效,包含当前shell进程的子进程。

2)变量赋值:

即向变量的存储空间保存数据,如下

[root@localhost ~]# VAR_NAME=VALUE
3)变量的引用

格式为:${VAR_NAME}

" ":弱引用,里面的变量会被替换;' ':强引用,里面的所有字符都是字面量,直接输出,所见即所得;
4)环境变量

对当前shell进程及其子shell有效,对其他的shell进程无效!

定义:VAR_NAME=VALUE导出:export VAR_NAME撤销变量:unset VAR_NAME只读变量:readonly VAR_NAME
5)局部变量

在shell脚本中定义,只可以在shell脚本中使用!

6)位置变量
$1,$2...,${10}
7)特殊变量

shell对一些参数做特殊处理,这些参数只能被引用而不能被赋值!

$#:传递到脚本的参数个数$*:显示所有向脚本传递的参数                  //与位置变量不同,此选项参数可超过9个$$:获取当前shell的进程号$!:执行上一个指令的进程号$?:获取执行的上一个指令的返回值              //0为执行成功,非零为执行失败$-:显示shell使用的当前选项,与set命令功能相同$@  与$*相同,但是使用时加引号,并在引号中返回每个参数
8)查看变量
set:查看当前shell进程中的所有变量;export、printenv、env:查看当前shell进程中的所有环境变量;
9)变量命名规则
1)不能使用程序中的关键字;2)只能使用数字、字母和下划线,不可使用数字开头;3)系统变量默认都是大写,自定义变量尽量不要与系统变量冲突;4)尽量做到见名知意;
10)变量类型
1)数值型:精确数值(整数)、近似数值(浮点数);2)字符型:char、string;3)布尔型:true、false;
11)类型转换
1)显示转换;2)隐式转换;

二、bash的配置文件

功能:设定本地变量、定义命令别名。

1)profile类

profile类:为交互式登录的用户提供配置!

全局:/etc/profile、/etc/profile.d/*.sh用户:~/.bash_profile
2)bashrc类

bashrc类:为非交互式的用户提供配置!

全局:/etc/bashrc用户:~/.bashrc

1)bash编程即编写格式及执行方式

1)编写格式

shell脚本第一行必须顶格写,用shabang定义指定的解释器来解释该脚本。

#!/bin/bash       //!即为shebang//其它的以#开头的行均为注释,会被解释器忽略,可用来注释脚本用途及版本,方便使用管理。
2)执行方式

bash编程属于面向过程编程,执行方式如下:

1)顺序执行:按命令先后顺寻依次执行;2)选择执行:测试条件,可能会多个测试条件,某条件满足时,则执行对应的分支;3)循环执行:将同一段代码反复执行多次,因此,循环必须有退出条件;否则,则陷入死循环;
3)bash执行选项
1)bash -n SHELLNAME  #语法测试,测试是否存在语法错误;2)bash -x SHELLNAME  #模拟单步执行,显示每一步执行过程;

2)bash之算数运算与逻辑运算

1)算数运算

定义整型变量:

1)et VAR_NAME=INTEGER_VALUE            //例如:let a=32)declare -i VAR_NAME=INTEGER_VALUE     //例如:declare -i a=3

实现算术运算的方式:

let VAR_NAME=ARITHMATIC_EXPRESSIONVAR_NAME=$[ARITHMATIC_EXRESSION]VAR_NAME=$((EXPRESSION))VAR_NAME=$(expr $num1 + $num2)

算法运算符:

+:加法-:减法*:乘法/:整除%:取余数**:乘幂

注意:即使没有定义为整型变量,字符型的数字依然可以参与算术运算,bash会执行变量类型的隐式类型转换。

2)逻辑运算
布尔运算:真,假与运算:真 && 真 = 真        真 && 假 = 假        假 && 真 = 假        假 && 假 = 假或运算:真 || 真 = 真  真 || 假 = 真  假 || 真 = 真  假 || 假 = 假非运算:!真=假        !假=真

3)bash编程之条件测试语句

1)bash条件测试

整型测试:整数比较

例如 [ $num1 -gt $num2 ]-gt: 大于-lt: 小于-ge: 大于等于-le: 小于等于-eq: 等于-ne: 不等于

字符测试:字符串比较

双目:例如[[ "$str1" > "$str2" ]]>: 大于则为真<: 小于则为真>=:大于等于则为真<=:小于等于则为真==:等于则为真!=:不等于则为真单目:-n String: 是否不空,不空则为真,空则为假-z String: 是否为空,空则为真,不空则假文件测试:判断文件的存在性及属性等-a FILE:存在则为真;否则则为假;-e FILE:存在则为真;否则则为假;-f FILE: 存在并且为普通文件,则为真;否则为假;-d FILE: 存在并且为目录文件,则为真;否则为假;-L/-h FILE: 存在并且为符号链接文件,则为真;否则为假;-b: 存在并且为块设备,则为真;否则为假;-c: 存在并且为字符设备,则为真;否则为假-S: 存在并且为套接字文件,则为真;否则为假-p: 存在并且为命名管道,则为真;否则为假-s FILE: 存在并且为非空文件则为值,否则为假;-r FILE:文件可读为真,否则为假-w FILE:文件可写为真,否则为假-x FILE:文件可执行为真,否则为假file1 -nt file2: file1的mtime新于file2则为真,否则为假;file1 -ot file2:file1的mtime旧于file2则为真,否则为假;组合条件测试:在多个条件间实现逻辑运算与:[ condition1 -a condition2 ]  condition1 && condition2或:[ condition1 -o condition2 ]  condition1 || condition2非:[ -not condition ]  ! condition与:COMMAND1 && COMMAND2COMMAND1如果为假,则COMMAND2不执行或:COMMAND1 || COMMAND2COMMAND1如果为真,则COMMAND2不执行非:! COMMAND
2)条件测试之if语句
1、if语句之单分支语句结构:if 测试条件;then   选择分支fi表示条件测试状态返回值为值,则执行选择分支例:写一个脚本,接受一个参数,这个参数是用户名;如果此用户不存在,则创建该用户;#!/bin/bashif ! id $1 &> /dev/null;then  useradd $1fi2、if语句之双分支语句结构:if 测试条件;then   选择分支1else   选择分支2fi两个分支仅执行其中之一例:通过命令行给定一个文件路径,而后判断:如果此文件中存在空白行,则显示其空白行的总数;否则,则显示无空白行;#!/bin/bashif grep "^[[:space]]*$" $1 &> /dev/null; then  echo "$1 has $(grep "^[[:space]]*$" $1 | wc -l) blank lines."else  echo "No blank lines"fi注意:如果把命令执行成功与否当作条件,则if语句后必须只跟命令本身,而不能引用。3、if语句之多分支语句结构:if 条件1;then     分支1elif 条件2;then     分支2elif 条件3;then     分支3      ...else     分支nfi例:传递一个用户名给脚本:如果此用户的id号为0,则显示说这是管理员;如果此用户的id号大于等于500,则显示说这是普通用户;否则,则说这是系统用户。#!/bin/bashif [ $# -lt 1 ]; then  echo "Usage: `basename $0` username"  exit 1fiif ! id -u $1 &> /dev/null; then  echo "Usage: `basename $0` username"  echo "No this user $1."  exit 2fiif [ $(id -u $1) -eq 0 ]; then  echo "Admin"elif [ $(id -u $1) -ge 500 ]; then  echo "Common user."else  echo "System user."fi
3)bash交互式编程
read [option] "prompt"-p:直接指定一个变量接受参数-t timaout:指定等待接受参数的时间-n:表示不换行例:输入用户名,可返回其shell#!/bin/bashread -p "Plz input a username: " userNameif id $userName &> /dev/null; then    echo "The shell of $userName is `grep "^$userName\>" /etc/passwd | cut -d: -f7`."else    echo "No such user. stupid."fi  
4)条件测试与case语句
case语句:有多个测试条件时,case语句会使得语法结构更明晰语句结构:case 变量引用 inPATTERN1)  分支1;;PATTERN2)  分支2;;...*)  分支n;;esac

PATTERN:类同于文件名通配机制,但支持使用|表示或者

 a|b:  a或者b*:匹配任意长度的任意字符?: 匹配任意单个字符[]: 指定范围内的任意单个字符例:写一个脚本,完成如下任务,其使用形式如下所示:script.sh {start|stop|restart|status}其中:如果参数为空,则显示帮助信息,并退出脚本;如果参数为start,则创建空文件/var/lock/subsys/script,并显示"starting script successfully."如果参数为stop,则删除文件/var/lock/subsys/script,并显示"Stop script successfully."如果参数为restart,则删除文件/var/locksubsys/script并重新创建,而后显示"Restarting script successfully."如果参数为status,那么:如果文件/var/lock/subsys/script存在,则显示"Script is running…",否则,则显示"Script is stopped."#!/bin/bashfile='/var/lock/subsys/script'case $1 instart)  if [ -f $file ];then  echo "Script is running..."    exit 3  else  touch $file  [ $? -eq 0 ] && echo "Starting script successfully."  fi  ;;stop)  if [ -f $file ];then  rm -rf $file  [ $? -eq 0 ] && echo "Stop script successfully."  else  echo "Script is stopped..."  exit 4  fi  ;;restart)  if [ -f $file ];then  rm -rf $file  [ $? -eq 0 ] && echo "Stop script successfully"  else   echo "Script is stopped..."  exit 5  fi  touch $file  [ $? -eq 0 ] && echo "Starting script successfully"  ;;status)  if [ -f $file ];then  echo "Script is running..."  else  echo "Script is stopped."  fi  ;;*)  echo "`basename $0` {start|stop|restart|status}"  exit 2  ;; esac

4)bash编程之循环语句

1)循环之for循环
1、for语句格式一语句结构:for 变量名 in 列表; do    循环体done列表:可包含一个或多个元素循环体:依赖于调用变量来实现其变化循环可嵌套退出条件:遍历元素列表结束例:求100以内所有正整数之和#!/bin/bashdeclare -i sum=0for i in {1..100}; do    let sum+=$idoneecho $sum2、for语句格式二for ((初始条件;测试条件;修改表达式)); do      循环体done先用初始条件和测试条件做判断,如果符合测试条件则执行循环体,再修改表达式,否则直接跳出循环。例:求100以内所有正整数之和(for二实现)#!/bin/bashdeclare -i sum=0for ((counter=1;$counter <= 100; counter++)); do  let sum+=$counterdoneecho $sum
2)循环之while语句

while循环语句适用于循环次数未知,或不适用for直接生成较大的列表!

语句结构:while 测试条件; do  循环体done测试条件为真,进入循环;测试条件为假,退出循环例1:求100以内所有偶数之和,要求使用取模方法#!/bin/bashdeclare -i counter=1declare -i sum=0while [ $counter -le 100 ]; do  if [ $[$counter%2] -eq 0 ]; then     let sum+=$counter  fi  let counter++ doneecho $sum例2:提示用户输入一个用户名,如果用户存在,就显示用户的ID号和shell;否则显示用户不存在;显示完成之后不退出,再次重复前面的操作,直到用户输入q或quit为止#!/bin/bashread -p "Plz enter a username: " userNamewhile [ "$userName" != 'q' -a "$userName" != 'quit' ]; do  if id $userName &> /dev/null; then     grep "^$userName\>" /etc/passwd | cut -d: -f3,7  else    echo "No such user."  firead -p "Plz enter a username again: " userNamedonewhile特殊用法:遍历文本文件语句结构:while read 变量名; do  循环体done < /path/to/somefile变量名,每循环一次,记忆了文件中一行文本例:显示ID号为偶数,且ID号同GID的用户的用户名、ID和SHELLwhile read line; do  userID=`echo $line | cut -d: -f3`  groupID=`echo $line | cut -d: -f4`  if [ $[$userID%2] -eq 0 -a $userID -eq $groupID ]; then     echo $line | cut -d: -f1,3,7  fidone < /etc/passwd
3)循环之until语句
语句结构:until 测试条件; do      循环体done测试条件为假,进入循环;测试条件为真,退出循环例:求100以内所有偶数之和,要求使用取模方法(until实现)#!/bin/bashdeclare -i counter=1declare -i sum=0until [ $counter -gt 100 ]; do  if [ $[$counter%2] -eq 0 ]; then     let sum+=$counter  fi  let counter++doneecho $sum例:提示用户输入一个用户名,如果用户存在,就显示用户的ID号和shell;否则显示用户不存在;显示完成之后不退出,再次重复前面的操作,直到用户输入q或quit为止(until实现)#!/bin/bashread -p "Plz enter a username: " userNameuntil [ "$userName" = 'q' -a "$userName" = 'quit' ]; do  if id $userName &> /dev/null; then   grep "^$userName\>" /etc/passwd | cut -d: -f3,7elseecho "No such user."firead -p "Plz enter a username again: " userNamedone
4)循环之循环控制和shift
循环控制命令:1)break:提前退出循环;2)break [N]: 退出N层循环;N省略时表示退出break语句所在的循环;3)continue: 提前结束本轮循环,而直接进入下轮循环;4)continue [N]:提前第N层的循环的本轮循环,而直接进入下轮循环;
5)死循环
#while体while true; do      循环体done#until体until false; do      循环体done例1:写一个脚本,判断给定的用户是否登录了当前系统(1) 如果登录了,则脚本终止;(2) 每5秒种,查看一次用户是否登录;#!/bin/bashwhile true; do    who | grep "gentoo" &> /dev/null    if [ $? -eq 0 ];thenbreak    fi    sleep 5doneecho "gentoo is logged."
6)shift

位置参数可以用shift命令左移,比如shift 3 表示原来的$4现在变成$1,原来的$5变成$2等等,原来的$1、$2、$3丢弃,$0不移动。不带参数的shift命令相当于shift 1。

我们知道,对于位置变量或命令行参数,其个数必须是确定的,或者当shell程序不知道其个数时,可以把所有参数一起复制给"$*"。若用户要求 Shell 在不知道位置变量个数的情况下,还能逐个的把参数一一处理,也就是在 $1 后为 $2,在 $2 后面为 $3 等。在 shift 命令执行前变量 $1 的值在 shift 命令执行后就不可用了。

实例一如下:

[root@localhost ~]# cat 1.sh#!/bin/bashwhile [ $# -ne 0 ]doecho "第一个参数为:$1  参数个数为:$#"shiftdone[root@localhost ~]# sh 1.sh 1 2 3 4第一个参数为:1  参数个数为:4第一个参数为:2  参数个数为:3第一个参数为:3  参数个数为:2第一个参数为:4  参数个数为:1

从上面例子中可以看出shift命令每执行一次,变量的个数($#)减1,而变量的值提前一位。

实例二如下:

[root@localhost ~]# cat 2.sh#!/bin/bashif [ $# -eq 0 ]thenecho "Usage:2.sh 参数"exit 1fisum=0while [ $# -ne 0 ]dosum=`expr ${sum} + $1`shiftdoneecho "sum is:${sum}"[root@localhost ~]# sh 2.sh 10 20 30sum is:60

shift命令还有一个重要用途,Bash定义了9个位置变量,从$1到$9,这并不意味这用户在命令行只能使用9个参数,借助shift命令可以访问多于9个的参数。

shift命令一次移动到参数的个数由其所带的参数指定,例如当shell程序处理完前9个命令行参数后,可以使用shift 9命令把$10移动到$1。

5)bash编程之函数

语法结构:

function F_NAME {       函数体  }或  F_NAME() {    函数体  }
可调用:使用函数名,函数名出现的地方,会被自动替换为函数;函数的返回值:函数的执行结果返回值:代码的输出函数中使用打印语句:echo, printf函数中调用的系统命令执行后返回的结果执行状态返回值:默认取决于函数体执行的最后一个命令状态结果自定义退出状态码:return [0-255]

注意:函数体运行时,一旦遇到return语句,函数即返回!

1)函数可以接收参数

在函数中调用函数参数的方式同脚本中调用脚本参数的方式:

位置参数$1, $2, …$#, $*, $@

实例:
要求如下:
1)提示用户输入一个可执行命令;
2)获取这个命令所依赖的所有库文件(使用ldd命令);
3)复制命令之/mnt/sysroot目录;
4)复制各库文件至/mnt/sysroot对应的目录中;

[root@localhost ~]# cat 1.sh#!/bin/bashtarget=/mnt/sysroot/[ -d $target ] || mkdir $targetpreCommand() {    if which $1 &> /dev/null; then  commandPath=`which --skip-alias $1`  return 0    else  echo "No such command."  return 1    fi}commandCopy() {    commandDir=`dirname $1`    [ -d ${target}${commandDir} ] || mkdir -p ${target}${commandDir}    [ -f ${target}${commandPath} ] || cp $1 ${target}${commandDir}}libCopy() {    for lib in `ldd $1 | egrep -o "/[^[:space:]]+"`; dolibDir=`dirname $lib`[ -d ${target}${libDir} ] || mkdir -p ${target}${libDir}[ -f ${target}${lib} ] || cp $lib ${target}${libDir}    done} read -p "Plz enter a command: " commanduntil [ "$command" == 'quit' ]; do  if preCommand $command &> /dev/null; then    commandCopy $commandPath    libCopy $commandPath  fi    exit 1done[root@localhost ~]# sh 1.shPlz enter a command: cat[root@localhost ~]# ls /mnt/sysroot/bin/cat[root@localhost ~]# ls /mnt/sysroot/bin  lib64
2)bash编程之信号捕捉

trap命令用于在shell程序中捕捉到信号,之后可以由三种反应方式:
1)执行一段程序来处理这一信号;
2)接收信号的默认操作;
3)忽略这一信号;

示例:
写一个脚本,能够ping探测指定网络内的所有主机是否在线,当没有执行完时可接收ctrl+c命令退出。

[root@localhost ~]# cat 1.sh#!/bin/bashquitScript() {   echo "Quit..."}    trap 'quitScript; exit 5' SIGINTcnetPing() {  for i in {1..254}; do    if ping -c 1 -W 1 $1.$i &> /dev/null; then      echo "$1.$i is up."     else      echo "$1.$i is down."    fi    done}bnetPing() {  for j in {0..255}; do    cnetPing $1.$j   done}anetPing() {for m in {0..255}; dobnetPing $1.$mdone}netType=`echo $1 | cut -d"." -f1`if [ $netType -ge 1 -a $netType -le 126 ]; thenanetPing $netTypeelif [ $netType -ge 128 -a $netType -le 191 ]; thenbnetPing $(echo $1 | cut -d'.' -f1,2)elif [ $netType -ge 192 -a $netType -le 223 ]; thencnetPing $(echo $1 | cut -d'.' -f1-3)elseecho "Wrong"exit 2fi[root@localhost ~]# sh 1.sh 192.168.1.1192.168.1.1 is down.192.168.1.2 is down.192.168.1.3 is down.192.168.1.4 is down.192.168.1.5 is down.192.168.1.6 is down.192.168.1.7 is down.192.168.1.8 is down.192.168.1.9 is down.192.168.1.10 is up.192.168.1.11 is down.^CQuit...

----------本次博文到此结束,感谢阅读----------

参数 变量 循环 用户 条件 命令 语句 测试 文件 脚本 函数 分支 运算 个数 编程 结构 进程 字符 循环体 方式 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 互联网科技公司华为 互联网科技公司的优势 中国互联网科技股 恒生科技互联网指数分析 银川新华互联网科技学校地址 上海电发互联网科技有限公司 博兴的互联网电子科技公司 广州慧亚互联网科技怎么样 栖莱科技互联网股份有限公司 科技互联网大厂 智腾互联网科技有限公司 成都互联网科技公司工作好不好 洛阳昕诺飞互联网科技有限公司 广西互联网科技孵化中心 中和天地互联网科技有限公司 山东有哪些互联网科技公司 深圳无忧互联网科技 吉林省码上互联网科技电话 知域互联网科技有限公司官网 武汉亿视互联网科技有限公司 互联网科技金融 贷财互联网科技 互联网科技英文翻译 科技大学互联网专业好不好 华脉科技工业互联网产品 深圳前海聚择互联网科技有限公司 成都互联网科技公司100强 金融科技与互联网金融相同和不同 广州恒生互联网科技有限 湖南诚度互联网科技有限公司
0