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

Linux Shell 变量扩展进阶:深入理解 ${} 特殊用法

Linux Shell 变量扩展进阶:深入理解 ${} 特殊用法

  • Linux Shell 变量扩展进阶:深入理解 ${} 特殊用法
    • 一、变量默认值与条件判断
      • 1. `${varname:-word}`:变量不存在或为空时使用默认值
      • 2. `${varname:+word}`:变量存在且非空时使用替代值
      • 3. `${varname:=word}`:变量不存在或为空时赋值并返回
      • 4. `${varname:?word}`:变量不存在或为空时报错
      • 总结:默认值操作对比
    • 二、模式匹配与字符串截取
      • 1. `${varname#pattern}`:从开头删除最短匹配
      • 2. `${varname##pattern}`:从开头删除最长匹配
      • 3. `${varname%pattern}`:从结尾删除最短匹配
      • 4. `${varname%%pattern}`:从结尾删除最长匹配
      • 模式匹配规则
      • 总结:模式匹配截取对比
    • 三、其他实用的 ${} 用法
      • 1. 字符串长度:${#varname}
      • 2. 子串提取:${varname:position:length}
    • 四、实际应用案例
      • 案例1:处理文件扩展名
      • 案例2:安全处理命令行参数
      • 案例3:解析路径信息
    • 总结

Linux Shell 变量扩展进阶:深入理解 ${} 特殊用法

在 Linux Shell 脚本中,变量扩展不仅仅是简单的 $var 替换。${} 语法提供了丰富的变量处理功能,包括默认值设置、字符串截取、条件判断等。掌握这些高级用法可以让你的脚本更简洁、更健壮。本文将详细介绍 ${} 的常用特殊用法,包括默认值操作和模式匹配截取。

一、变量默认值与条件判断

当处理变量时,我们经常需要应对变量未定义、为空或非空的情况。Shell 提供了四种常用的默认值处理语法:

1. ${varname:-word}:变量不存在或为空时使用默认值

作用:如果 varname 未定义或为空(值为空字符串),则返回 word;否则返回变量本身的值。

示例

# 未定义变量
echo ${undefined_var:-"默认值"}  # 输出:默认值# 空变量
empty_var=""
echo ${empty_var:-"默认值"}      # 输出:默认值# 已定义且非空的变量
name="Linux"
echo ${name:-"默认值"}           # 输出:Linux

应用场景:为可能未设置的变量提供默认值,避免脚本出错。

2. ${varname:+word}:变量存在且非空时使用替代值

作用:如果 varname 已定义且非空,则返回 word;否则返回空值。

示例

# 未定义变量
echo "结果: ${undefined_var:+替代值}"  # 输出:结果: # 空变量
empty_var=""
echo "结果: ${empty_var:+替代值}"      # 输出:结果: # 已定义且非空的变量
name="Linux"
echo "结果: ${name:+替代值}"           # 输出:结果: 替代值

应用场景:仅当变量有有效值时执行特定操作,如:

# 如果配置文件存在,则加载它
config_file="app.conf"
[ -f ${config_file:+$config_file} ] && source $config_file

3. ${varname:=word}:变量不存在或为空时赋值并返回

作用:如果 varname 未定义或为空,则将 word 赋值给 varname 并返回 word;否则返回变量本身的值。

示例

# 未定义变量
echo ${undef_var:="新值"}  # 输出:新值
echo $undef_var            # 输出:新值(变量已被赋值)# 空变量
empty_var=""
echo ${empty_var:="新值"}  # 输出:新值
echo $empty_var            # 输出:新值(变量已被更新)# 已定义且非空的变量
name="Linux"
echo ${name:="新值"}       # 输出:Linux(变量值不变)

应用场景:初始化变量,确保后续操作中有可用的值:

# 确保日志目录存在,不存在则设置默认值
${LOG_DIR:="/var/log/myapp"}
mkdir -p $LOG_DIR  # 现在可以安全使用该变量

4. ${varname:?word}:变量不存在或为空时报错

作用:如果 varname 未定义或为空,则将 word 作为错误信息输出到标准错误并终止脚本;否则返回变量本身的值。

示例

# 未定义变量
echo ${undef_var:?"变量未定义"}  # 输出:bash: undef_var: 变量未定义(脚本终止)# 空变量
empty_var=""
echo ${empty_var:?"变量为空"}    # 输出:bash: empty_var: 变量为空(脚本终止)# 已定义且非空的变量
name="Linux"
echo ${name:?"错误信息"}         # 输出:Linux(正常执行)

应用场景:验证脚本必需的参数或变量,确保它们已正确设置:

# 脚本必须提供一个文件名参数
filename=$1
${filename:?"请提供文件名作为参数"}  # 如果未提供参数,脚本将报错退出

总结:默认值操作对比

语法变量未定义变量为空变量非空副作用
${var:-word}返回 word返回 word返回 var
${var:+word}返回空返回空返回 word
${var:=word}返回 word 并赋值返回 word 并赋值返回 var修改变量
${var:?word}报错退出报错退出返回 var可能终止脚本

二、模式匹配与字符串截取

${} 还提供了基于模式匹配的字符串截取功能,通过 ###%%% 符号实现从开头或结尾删除匹配的子串。

1. ${varname#pattern}:从开头删除最短匹配

作用:从变量值的开头开始,删除与 pattern 匹配的最短子串,返回剩余部分。

示例

path="/usr/local/bin/python"# 删除从开头到第一个 / 的部分
echo ${path#/}          # 输出:usr/local/bin/python# 删除从开头到第一个 . 的部分(没有匹配则返回原值)
echo ${path#*.}         # 输出:/usr/local/bin/python# 删除协议部分(如 http:// 或 https://)
url="https://example.com/path"
echo ${url#*://}        # 输出:example.com/path

2. ${varname##pattern}:从开头删除最长匹配

作用:从变量值的开头开始,删除与 pattern 匹配的最长子串,返回剩余部分。

示例

path="/usr/local/bin/python"# 删除从开头到最后一个 / 的部分(获取文件名)
echo ${path##*/}        # 输出:python# 获取文件路径中的文件名(与上面效果相同)
file="/home/user/docs/report.pdf"
echo ${file##*/}        # 输出:report.pdf# 从路径中获取目录部分
echo ${path##/usr}      # 输出:/local/bin/python

3. ${varname%pattern}:从结尾删除最短匹配

作用:从变量值的结尾开始,删除与 pattern 匹配的最短子串,返回剩余部分。

示例

file="document.txt.bak"# 删除最后一个 . 及其后面的部分
echo ${file%.*}         # 输出:document.txt# 从路径中删除文件名,保留目录
path="/usr/local/bin/python"
echo ${path%/*}         # 输出:/usr/local/bin# 处理没有扩展名的文件
simple_file="readme"
echo ${simple_file%.*}  # 输出:readme(无变化)

4. ${varname%%pattern}:从结尾删除最长匹配

作用:从变量值的结尾开始,删除与 pattern 匹配的最长子串,返回剩余部分。

示例

file="document.txt.bak"# 删除所有 . 及其后面的部分
echo ${file%%.*}        # 输出:document# 处理多层目录
path="/a/b/c/d/file.txt"
echo ${path%%/*}        # 输出:(空字符串,因为匹配了从第一个 / 到结尾的所有内容)# 更实用的例子:获取不带任何扩展名的文件名
archive="data.tar.gz"
echo ${archive%%.*}     # 输出:data

模式匹配规则

上述用法中的 pattern 支持通配符:

  • *:匹配任意长度的任意字符
  • ?:匹配单个任意字符
  • [abc]:匹配 a、b 或 c 中的任意一个
  • [!abc]:匹配除 a、b、c 之外的任意字符

示例

text="abc123def456"# 从开头删除到第一个数字
echo ${text#[!0-9]*}    # 输出:123def456# 从结尾删除最后一个数字及之后的内容
echo ${text%[0-9]*}     # 输出:abc123def4

总结:模式匹配截取对比

语法作用匹配方向匹配长度典型用途
${var#pattern}从开头删除匹配部分从左到右最短匹配移除前缀
${var##pattern}从开头删除匹配部分从左到右最长匹配获取文件名
${var%pattern}从结尾删除匹配部分从右到左最短匹配移除后缀
${var%%pattern}从结尾删除匹配部分从右到左最长匹配移除所有扩展名

三、其他实用的 ${} 用法

除了上述两大类,${} 还有一些常用功能:

1. 字符串长度:${#varname}

作用:返回变量值的长度(字符数)。

示例

name="Linux"
echo ${#name}  # 输出:5text="Hello World"
echo ${#text}  # 输出:11(包含空格)

2. 子串提取:${varname:position:length}

作用:从 position 开始(0 为起始位置),提取长度为 length 的子串。length 可选,不指定则提取到结尾。

示例

str="abcdefgh"echo ${str:2}    # 输出:cdefgh(从位置2开始)
echo ${str:2:3}  # 输出:cde(从位置2开始,提取3个字符)
echo ${str: -3}  # 输出:fgh(负数表示从结尾开始计数)

四、实际应用案例

结合上述功能,我们可以实现一些实用的脚本功能:

案例1:处理文件扩展名

filename="report.pdf.bak"# 获取文件名(无扩展名)
echo ${filename%%.*}  # 输出:report# 获取扩展名(最后一个)
echo ${filename##*.}  # 输出:bak# 获取第一个扩展名
echo ${filename#*.}   # 输出:pdf.bak

案例2:安全处理命令行参数

# 脚本名:process.sh
# 用法:./process.sh <输入文件> [输出目录]# 检查必需参数
input_file=$1
${input_file:?"请提供输入文件作为第一个参数"}# 设置输出目录默认值
output_dir=${2:-"./output"}# 确保输出目录存在
mkdir -p $output_direcho "处理文件: $input_file"
echo "输出目录: $output_dir"

案例3:解析路径信息

full_path="/usr/local/share/doc/readme.txt"# 获取目录部分
dir_path=${full_path%/*}
echo "目录: $dir_path"  # 输出:目录: /usr/local/share/doc# 获取文件名(含扩展名)
file_name=${full_path##*/}
echo "文件名: $file_name"  # 输出:文件名: readme.txt# 获取文件名(不含扩展名)
base_name=${file_name%.*}
echo "基础名称: $base_name"  # 输出:基础名称: readme

总结

${} 语法为 Shell 变量处理提供了强大的功能,掌握这些用法可以:

  1. 更优雅地处理变量默认值和边界情况
  2. 无需调用外部命令(如 sedawk)即可完成字符串处理
  3. 使脚本更简洁、高效且易于维护

重点记住:

  • :-:+:=:? 用于变量默认值和条件判断
  • ###%%% 用于基于模式的字符串截取
  • 这些操作都是 Shell 内置功能,比调用外部命令性能更好

若有转载,请标明出处:https://blog.csdn.net/CharlesYuangc/article/details/152365841

http://www.dtcms.com/a/430713.html

相关文章:

  • 04.CSS 动画效果| 仅使用 HTML 和 CSS
  • Matlab通过GUI实现点云的快速全局配准(FGR)
  • 晋城网站开发合肥网站策划
  • EfficientNet模型:高效卷积神经网络的革命性突破
  • 软件测试基础-day1
  • Linux安装centos8及基础配置
  • OpenSpeedy官网下载 - 百度网盘加速器,开箱即用的游戏变速器
  • 【MySQL】MySQL环境搭建
  • HEFrame.WpfUI :一个现代化的 开源 WPF UI库
  • Stanford CS336 Lecture3 | Architectures, hyperparameters
  • NotoSansSC-Regular.otf介绍与下载
  • 顺丰物流网站建设策划书wordpress订阅者投稿
  • 自动生成手机网站wordpress 福利吧主题
  • 前端项目:智能问卷调研系统
  • 网站悬浮窗广告怎么做WordPress集成tipask
  • Ruby 安装 - Windows
  • OSPF报文概念及题目
  • 通信中间件 Fast DDS(三) :fastddsgen的安装与使用
  • Xcode上编译调试ffmpeg
  • Unity游戏基础-2(初识场景~项目构建)
  • 计算机网络第四章(4)——网络层《IPV6》
  • 陕西省建设厅网站首页官方网站下载zoom
  • 降低查询范围
  • 51——DS1302
  • 语校网500所里程碑:日本语言学校数据库的标准化与可追溯机制
  • wordpress 站长主题商城系统源码
  • docker快速使用yolov11
  • 鸿蒙NEXT SSAP连接与数据传输实战:轻松实现跨设备通信
  • 第10章 Docker
  • 【迭代】本地高性能c++对话系统e2e_voice