Shell 变量

以下是关于 Shell 变量 的详细讲解,涵盖定义、类型、使用方法及常见操作:


1. Shell 变量的定义与命名规则

定义方式
  • 使用 = 连接变量名和值,等号两侧不能有空格

  • 如果值包含空格或特殊字符,需要用引号(单引号或双引号)包裹。

    • 单引号里的任何字符都会原样输出,单引号字符串中的变量是无效的
    • 双引号里可以有变量、可以有转义字符
    # 正确示例
    my_var=Hello World'
    path="/usr/local/bin"
    my_path="/path with space"
    
    # 错误示例
    my var="Hello World"  # 等号两侧不能有空格
    
命名规则
  1. 字符限制:只能由字母(a-z, A-Z)、数字(0-9)和下划线(_)组成。

  2. 首字符限制:必须以字母或下划线开头,不能以数字开头。

  3. 大小写敏感VARvar 是两个不同的变量。

  4. 描述性:建议使用有意义的名称(如 count 表示计数,file_path 表示文件路径)。

    1Invalid="Valid"
    

2. 变量的引用

基本引用
  • 使用 $变量名${变量名} 引用变量值:

    name="Alice"
    echo "Hello, $name"         # 输出: Hello, Alice
    echo "Hello, ${name}!"      # 输出: Hello, Alice!
    
复杂场景
  • 避免歧义:当变量名后紧跟其他字符时,用 ${} 明确边界:

    count=5
    echo "Count is $count6"     # 输出: Count is 6 (可能被解析为 $count6)
    echo "Count is ${count}6"   # 输出: Count is 56
    

3. 特殊变量

Shell 提供了一些预定义变量,用于脚本参数传递和状态管理:

变量作用
$0脚本名称(包括路径)
$nn 个参数(n 为 1~9,超过 9 用 ${10} 等)
$#传递给脚本的参数总个数
$*所有参数作为一个字符串("$*" 会合并为单个字符串)
$@所有参数作为独立字符串("$@" 保留每个参数的独立性)
$?上一条命令的退出状态码(0 表示成功,非 0 表示失败)
$$当前 Shell 脚本的进程 PID
$!上一个后台进程的 PID
$_上一条命令的最后一个参数

示例

#!/bin/bash
echo "脚本名称: $0"
echo "第一个参数: $1"
echo "参数总数: $#"
echo "所有参数: $@"

运行命令:

./script.sh arg1 arg2

输出:

脚本名称: ./script.sh
第一个参数: arg1
参数总数: 2
所有参数: arg1 arg2

4. 环境变量 vs 本地变量

本地变量
  • 仅在当前 Shell 会话中有效,退出后失效。

  • 定义:var="value"

  • 示例:

    name="Alice"
    echo $name  # 输出: Alice
    exit
    echo $name  # 输出为空(退出后变量失效)
    
环境变量
  • 对当前 Shell 及其子进程可见。

  • 定义:export var="value"

  • 示例:

    export PATH="$PATH:/custom/path"
    

5. 变量操作

字符串操作
  • 字符串替换

    • Shell 提供了内置的变量替换语法

      无需调用外部命令,性能较高

      ${variable/pattern/replacement}
      

      替换第一个匹配项

      str="hello world"
      echo ${str/hello/hi}  # 输出: hi world
      

      替换所有匹配项

      str="apple banana apple"
      echo ${str//apple/orange}  # 输出: orange banana orange
      

      替换特殊字符(如 /)

      path="c:/windows/boot.ini"
      echo ${path//\//\\}  # 输出: c:\windows\boot.ini
      
    • sed命令:

      是一个流编辑器,适合处理文件或字符串的复杂替换操作

      sed 's/pattern/replacement/' input
      

      替换第一个匹配项

      echo "hello world" | sed 's/hello/hi/'  # 输出: hi world
      

      全局替换(所有匹配项)

      echo "apple banana apple" | sed 's/apple/orange/g'  # 输出: orange banana orange
      

      替换文件内容

      sed -i 's/old/new/g' filename.txt  # 直接修改文件内容
      

      正则表达式替换

      echo "2025-06-21" | sed 's/-/./g'  # 输出: 2025.06.21
      
    • awk命令:

      是一种文本处理工具,适合按字段处理字符串替换

      awk '{gsub(/pattern/, "replacement"); print}' input
      

      全局替换

      echo "apple banana apple" | awk '{gsub(/apple/, "orange"); print}'  # 输出: orange banana orange
      

      按字段替换

      echo "www.baidu.com" | awk -F. '{ $1 = "new"; OFS="."; print }'  # 输出: new.baidu.com
      
    • perl 命令:

      提供了强大的正则表达式替换功能,适合复杂场景

      perl -pe 's/pattern/replacement/' input
      

      示例

      echo "2025-06-21" | perl -pe 's/-/./g'  # 输出: 2025.06.21
      
    • tr

      用于字符级别的替换、删除或压缩,适合处理单字符替换

      tr 'SET1' 'SET2' < input
      

      字符替换

      echo "hello" | tr 'aeiou' 'AEIOU'  # 输出: hEllO
      

      删除字符

      echo "hello 123" | tr -d '0-9'  # 输出: hello 
      

      压缩重复字符

      echo "aaabbbccc" | tr -s 'a'  # 输出: abbbccc
      
  • 字符串截取

    • 从指定位置截取

      ${string:start:length}
      
      • string:目标字符串。
      • start:起始位置(从左往右数时,从 0 开始;从右往右数时,从 -1 开始)。
      • length:截取长度(可省略,省略时截取到字符串末尾)。
    • 按指定字符截取

      截取右边字符(从匹配字符后开始截取):

      ${string#*chars}   # 匹配第一个 chars
      ${string##*chars}  # 匹配最后一个 chars
      

      截取左边字符(从右往左):

      ${string%chars*}   # 匹配从右往左第一个 chars
      ${string%%chars*}  # 匹配从右往左最后一个 chars
      

      示例:

      url="https://blog.youkuaiyun.com/qq_41964263"
      
      # 从第一个 ":" 后截取
      echo ${url#*:}       # 输出 "//blog.youkuaiyun.com/qq_41964263"
      
      # 从最后一个 "/" 后截取
      echo ${url##*/}      # 输出 "qq_41964263"
      
      # 从从右往左第一个 "/" 前截取
      echo ${url%/*}       # 输出 "https://blog.youkuaiyun.com"
      
      # 从从右往左最后一个 "." 前截取
      echo ${url%%/*}      # 输出 "https:"
      

      💥*是通配符的一种,表示任意字符串,如果不需要模糊匹配 chars 左边/右边的字符,那么也可以不写通配符*

      url="https://blog.youkuaiyun.com/qq_41964263"
      echo ${url#https:}       # 输出 "//blog.youkuaiyun.com/qq_41964263"
      
  • 获取字符串长度

    • 使用 ${#string}(推荐)

      这是 Bash 内置的语法,直接通过变量名获取字符串长度,高效且简洁。

      str="Hello World"
      length=${#str}
      echo "字符串长度为: $length"
      
默认值与条件赋值
  • 默认值:如果变量未设置或为空,提供默认值:

    user=${USER:-default_user}
    echo $user  # 如果 USER 未设置,输出 default_user
    
  • 条件赋值:如果变量未设置,报错并退出:

    file=${1?"No file specified"}
    echo $file  # 如果未传参数,脚本终止并提示错误
    

6. 只读变量与取消变量

只读变量
  • 使用 readonly 声明只读变量,不可修改或删除:

    readonly PI=3.14
    PI=3.1415  # 报错: cannot overwrite: readonly variable
    
取消变量
  • 使用 unset 删除变量:

    unset var_name
    echo $var_name  # 输出为空
    

7. 变量作用域

  • 局部变量:仅在当前 Shell 脚本中有效。
  • 环境变量:通过 export 导出后,对子进程可见。
  • 父子 Shell 的继承
    • 子 Shell 可以继承父 Shell 的环境变量。
    • 在子 Shell 中定义的变量,父 Shell 不可见。

8. 实际应用场景

处理脚本参数
#!/bin/bash
echo "欢迎 $1$2!"

运行命令:

./welcome.sh Alice 优快云

输出:

欢迎 Alice 到 优快云!
动态文件路径
dir="/home/user"
file="data.txt"
full_path="${dir}/${file}"
cat $full_path
日志记录
log_file="/var/log/my_script.log"
echo "[$(date)] Script started" >> $log_file

总结

  • Shell 变量是脚本编程的核心,灵活使用变量可以简化复杂操作。
  • 注意变量作用域(本地 vs 环境变量)和引用方式($var vs ${var})。
  • 利用特殊变量($#, $@, $?)处理脚本参数和状态码。
  • 字符串操作(替换、截取)和条件赋值能提升脚本的健壮性。

👍 时间不会回头,人生没有重来
😊 希望对你有帮助!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

咖啡续命又一天

一杯续命美式,续写下一篇干货

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值