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

Shell脚本编程——变量用法详解

一、变量基础概念

1.1 什么是变量?

变量是命名的内存空间,用于存储数据(如字符串、数字等)。通过变量名可以快速引用和操作这些数据,避免重复输入复杂内容。

1.2 变量的作用

  • 简化操作​:用有意义的名称代替重复的数据(如 PATH=/usr/bin:/usr/local/bin)。

  • 灵活控制​:通过修改变量值动态调整脚本行为(如根据用户输入切换路径)。

  • 提高可读性​:清晰的变量名让代码更易理解(如 USER_NAME=admin比直接写 admin更直观)。


二、变量类型

Shell中的变量按用途和特性分为以下几类:

类型

说明

示例

内置变量

Shell预定义的系统变量(只读或全局生效),如 PATH(命令搜索路径)、UID(用户ID)

echo $PATH查看命令搜索路径

用户自定义变量

用户手动定义的变量,用于存储脚本中需要的数据

name="Tom"

预定义变量

Shell内置的特殊变量(如 $0$?),用于获取脚本执行相关信息

$0表示脚本名称,$?表示上一条命令的退出状态

位置变量

用于接收脚本运行时传递的参数(如 $1$2...),对应第1、第2个参数

执行 ./script.sh arg1 arg2时,$1arg1$2arg2

2.1 变量数据类型

  • 字符串​:文本数据(如 "Hello"'World'),Shell默认所有变量均为字符串。

  • 数值​:

    • 整型​:整数(如 10-5),Bash可直接处理。

    • 浮点型(小数)​​:Bash不支持​(如 3.14需借助外部工具如 bc计算)。


三、变量命名规则

3.1 合法命名要求

  • 字符限制​:只能包含 ​数字、字母、下划线​(如 user_nameAGE_20)。

  • 禁止数字开头​:不能以数字开头(如 1name❌,name1✅)。

  • 避开保留字​:不能使用Shell关键字(如 ifforwhile)。

  • 推荐命名风格​:

    • 见名思义​:变量名体现用途(如 usernamea更清晰)。

    • 统一规范​:

      • 全大写​:环境变量或全局常量(如 PATHMAX_SIZE)。

      • 小写​:局部变量和函数名(如 countcalculate_sum)。


四、变量的定义与使用

4.1 定义变量

格式:变量名="值"(等号两侧不能有空格​!)

常见赋值方式:

name='Mike'                  # 直接字符串(单引号包裹,内容原样输出)
NAME="$USER"                 # 引用其他变量(双引号内变量会被解析)
hostname=`hostname`          # 命令结果(反引号,旧写法)
hostname=$(hostname)         # 命令结果(推荐,更清晰的 $( ) 写法)
FILE=/etc/*                  # 通配符(匹配 /etc 下所有文件)

⚠️ 注意:变量赋值仅在当前Shell进程中有效,关闭终端后自动失效(除非写入配置文件如 ~/.bashrc)。

4.2 引用变量

  • 基本引用​:$变量名(如 echo $name)或 ${变量名}(推荐,避免歧义)。

  • 弱引用 vs 强引用​:

    • 弱引用 $var​:变量会被替换为实际值(如 echo "Name: $name"→ 输出 Name: Mike)。

    • ​**强引用 'var′‘∗∗:变量保持原字符串(如‘echo′Name:name'→ 输出Name: $name`)。

4.3 特殊场景:变量名相邻时的处理

若变量名与其他字符相连(如 ${NAME}_AGE),必须用 ${ }明确边界,否则Shell会误解析:

NAME=mage
echo $NAME_AGE    # 错误!Shell尝试找变量 NAME_AGE(不存在,默认为空)
echo ${NAME}_AGE  # 正确!输出 "mage_AGE"

五、变量作用域

变量的生效范围(作用域)决定了它能在哪些Shell进程中使用:

类型

生效范围

示例场景

普通变量

当前Shell进程

在终端直接定义的变量(如 name="Tom"),子Shell(如新开的终端窗口)无法访问。

环境变量

当前Shell及其所有子进程

通过 export 变量名=value定义(如 export PATH=/new/path:$PATH),子进程可继承。

本地变量

当前Shell的某个代码片段(如函数内部)

函数内定义的变量(默认仅函数内可用,除非用 local声明为局部变量)。

📌 环境变量通常用于配置全局信息(如 PATH),普通变量多用于脚本内部临时存储。


六、常用变量操作命令

6.1 查看所有变量

  • set:显示所有变量(包括用户自定义、环境变量、函数等)。

  • envprintenv:仅显示环境变量。

  • export:显示已导出的环境变量。

  • declare -x:同 export,显示环境变量。

6.2 删除变量

unset 变量名1 变量名2  # 删除指定变量(如 unset name age)

删除后,该变量不可再被引用(echo $变量名输出空)。


七、特殊变量详解

7.1 环境变量

  • 作用​:子进程(包括孙子进程)可继承父进程的环境变量,但子进程的修改不会影响父进程。

  • 定义方法​:

    export 变量名=value      # 推荐写法(先赋值再导出)
    变量名=value; export 变量名  # 分步写法
    declare -x 变量名=value  # 使用 declare 命令
  • 示例​:让子脚本使用父脚本定义的变量

    # father.sh
    #!/bin/bash
    NAME="father"
    export NAME             # 导出为环境变量
    echo "Father: $NAME"
    ./son.sh                # 调用子脚本# son.sh
    #!/bin/bash
    echo "Son: $NAME"       # 子脚本可访问父脚本导出的 NAME
    NAME="son"              # 子脚本修改自己的 NAME(不影响父脚本)
    echo "Son修改后: $NAME"

7.2 只读变量

  • 特点​:定义后不可修改、不可删除,用于存储固定值(如配置常量)。

  • 定义方法​:

    readonly 变量名=value
    declare -r 变量名=value
  • 示例​:

    readonly PI=3.14
    PI=3.14159  # 报错:PI: 只读变量
    unset PI    # 报错:无法删除只读变量

7.3 位置变量

用于接收脚本运行时传递的参数(通过命令行传入):

变量

说明

示例(执行 ./script.sh A B C

$0

脚本名称(含路径)

./script.sh或完整路径

$1

第1个参数

A

$2

第2个参数

B

...

...

...

$9

第9个参数

(超过9需用 ${10}语法)

$#

参数的总个数

3(对应 A/B/C)

$*

所有参数合并为单个字符串

A B C

$@

所有参数为独立字符串

ABC(双引号内差异明显)

$?

上一条命令的退出状态码

0(成功)或非0(失败)

$$

当前Shell进程的PID

脚本自身的进程ID

📌 ​注意​:$*$@在双引号中表现不同:

  • "$*":所有参数合并为一个字符串(如 "A B C")。

  • "$@":每个参数作为独立字符串(如 "A" "B" "C"),推荐在循环中遍历参数时使用。

7.4 退出状态码变量 $?

  • 作用​:存储上一条命令或函数的执行结果(0表示成功,非0表示失败)。

  • 常见状态码​:

    • 0:成功。

    • 1:一般错误(如参数错误)。

    • 127:命令未找到(如输入了错误的命令名)。

  • 自定义退出​:通过 exit n主动设置脚本退出状态(如 exit 0表示成功)。


八、变量操作进阶

8.1 命令替换

通过命令执行结果赋值给变量:

# 反引号(旧写法)
current_date=`date +%Y-%m-%d`# 推荐写法($( ))
current_dir=$(pwd)
files_count=$(ls | wc -l)

8.2 数值计算(整型)

Bash默认不支持浮点数,但可通过 $(( ))let进行整数运算:

a=10
b=20
sum=$((a + b))      # sum=30
let "product=a*b"   # product=200

8.3 展开命令行规则

Shell处理命令行时按以下顺序:

  1. 1.

    拆分命令词 → 2. 展开别名 → 3. 处理 {}大括号 → 4. 处理 ~家目录 → 5. 命令替换 $( )` `→ 6. 再次拆分词 → 7. 处理通配符 */?→ 8. 准备输入/输出重定向 </>→ 9. 执行命令。

8.4 防止扩展(避免特殊字符被解析)

  • ​**反斜线 \`**:转义单个字符(如echo Your cost: $5.00→ 输出Your cost: $5.00`)。

  • 引号​:

    • 单引号 ' '​:禁止所有扩展(如 echo '$PATH'→ 输出 $PATH)。

    • 双引号 " "​:允许部分扩展(如变量 $VAR会被解析,但命令替换 ` `$( )仍生效)。


九、实战示例

示例1:显示系统信息脚本(OS.sh)

#!/bin/bash
RED="\E[1;31m"
GREEN="\E[1;32m"
END="\E[0m"
echo -e "${GREEN}----------Host systeminfo----------${END}"
echo -e "HOSTNAME: ${RED}$(hostname)${END}"
echo -e "IPADDR:   ${RED}$(ifconfig ens160 | grep -Eo '([0-9]{1,3}\.){3}[0-9]{1,3}' | head -n1)${END}"
echo -e "OSVERSION: ${RED}$(cat /etc/redhat-release)${END}"
echo -e "KERNEL:   ${RED}$(uname -r)${END}"
echo -e "CPU:       ${RED}$(lscpu | grep "型号名称:" | tr -s ' ' ' '|cut -d ' ' -f 2-5)${END}"
echo -e "MEMORY:   ${RED}$(free -h | grep Mem | tr -s ' ' ' '|cut -d ' ' -f 4)${END}"
echo -e "DISK:     ${RED}$(lsblk | grep '^sda' | tr -s ' ' | cut -d ' ' -f 4)${END}"
echo -e "${GREEN}----------       END     ----------${END}"

运行:chmod +x OS.sh && ./OS.sh

示例2:通过变量动态执行命令

CMD=hostname
$CMD  # 实际执行 hostname 命令,输出当前主机名

十、总结

  • 变量是Shell脚本的核心​:合理使用变量能让脚本更灵活、可维护。

  • 命名规范是关键​:遵循规则(如避免数字开头、用有意义的名字)减少错误。

  • 作用域决定使用场景​:普通变量用于脚本内部,环境变量用于跨进程传递信息。

  • 特殊变量(如 $1$?)是脚本交互的基础​:掌握它们才能编写实用的参数处理和错误判断逻辑。

http://www.xdnf.cn/news/19257.html

相关文章:

  • Ruoyi-vue-plus-5.x第二篇MyBatis-Plus数据持久层技术:2.2 分页与性能优化
  • DAY17-新世纪DL(DeepLearning/深度学习)战士:Q(机器学习策略)2
  • AI 应用 图文 解说 (二) -- 百度智能云 ASR LIM TTS 语音AI助手源码
  • 自定义AXI_PWM_v1.0——ZYNQ学习笔记15
  • Spring Task快速上手
  • Maven学习笔记01
  • 【stm32】对射式红外传感器计次以及旋转编码器计次
  • SpringBoot 自研运行时 SQL 调用树,3 分钟定位慢 SQL!
  • 用产品经理的思维,重构AI时代的增长Playbook
  • 企业数据湖:从混沌到秩序的分层设计与治理策略
  • 11.1.5 实现文件删除,共享和共享下载排行榜
  • 分布式测试平台ITP:让自动化测试更高效、更稳定
  • SW - 用装配图的方式组合多个子零件然后转换成为零件,可维护性好
  • 组件通信终极指南:从Props Drilling到Context API
  • react-virtualized React 应用中高效渲染大型列表和表格数据的库
  • 扣子(coze)实践指南进阶篇——创建工作流,并将工作流接入智能体
  • 2025年8月个人工作生活总结
  • [Windows] 某音下载工具——自用
  • Selenium 等待机制:编写稳定可靠的自动化脚本
  • Kubernetes中kubeadm、kubectl、kubelet的区别与作用
  • 动态规划入门(三):一些经典动态规划模型
  • arnold图像加密(猫脸变换)
  • 一个从7zip中分离出来的高压缩比文本压缩工具ppmd
  • 文件系统深度解析:从核心概念到代码实践
  • 【MLLM】多模态理解Ovis2.5模型和训练流程(更新中)
  • 手写MyBatis第43弹:插件拦截原理与四大可拦截对象详解
  • Shell脚本编程入门:从基础语法到流程控制
  • USB4 vs USB3.0:一场接口技术的革命性飞跃
  • 鸿蒙ArkTS 核心篇-14-条件表达式(三目运算符)
  • 如何提高微型导轨的生产效率?