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

shell之扩展

Shell脚本中的参数扩展(Parameter Expansion)是一项强大且灵活的功能,它允许你对变量的值进行操作、转换和计算。下面我将为你详细讲解常见的参数扩展用法。

先了解基础

参数扩展的基本形式是 ${parameter},用于获取变量 parameter的值。花括号 {}在多数情况下是可选的,但当变量名后紧接其他字符时,它们能明确界定变量名的范围。

1. 处理默认值和空值

这类扩展用于在变量未设置或为空时提供备选值或执行操作。

  • ${parameter:-word}​:若 parameter未设置或为空,则扩展为 word;否则扩展为 parameter的值。parameter自身的值不会改变

    unset var; echo "Result: ${var:-default}"  # 输出: Result: default
    var="custom"; echo "Result: ${var:-default}" # 输出: Result: custom
    echo "var is still: $var"                   # 输出: var is still: custom
  • ${parameter:=word}​:若 parameter未设置或为空,则将其设置为 word并扩展为 word;否则扩展为 parameter的值。​注意​:不能用于位置参数和特殊参数。

    unset var; echo "Result: ${var:=default}"  # 输出: Result: default
    echo "var is now: $var"                    # 输出: var is now: default
    var="custom"; echo "Result: ${var:=default}" # 输出: Result: custom
  • ${parameter:?word}​:若 parameter未设置或为空,则将 word(或默认错误消息)输出到标准错误​(stderr)并退出脚本;否则扩展为 parameter的值。常用于强制要求提供参数。

    unset var; : ${var:?Error: var is not set} # 输出到stderr: bash: var: Error: var is not set 并退出
    var="ok"; echo "Result: ${var:?Error}"     # 输出: Result: ok
  • ${parameter:+word}​:若 parameter已设置且不为空,则扩展为 word;否则不进行任何替换​(扩展为空)。这类似于一种“条件替换”。

    unset var; echo "Result: ${var:+replaced}"  # 输出: Result: 
    var="value"; echo "Result: ${var:+replaced}" # 输出: Result: replaced
    echo "var remains: $var"                   # 输出: var remains: value

2. 操作字符串:删除与替换

这类扩展用于对变量存储的字符串进行模式匹配和修改。

  • ${parameter#pattern}​:从 parameter值的开头删除与 pattern匹配的最短部分。

    path="/usr/local/bin"; echo "${path#*/}"    # 输出: usr/local/bin (删除最短的`*/`,即第一个`/`及之前)
  • ${parameter##pattern}​:从 parameter值的开头删除与 pattern匹配的最长部分。

    path="/usr/local/bin"; echo "${path##*/}"   # 输出: bin (删除最长的`*/`,即最后一个`/`及之前的所有内容)
  • ${parameter%pattern}​:从 parameter值的末尾删除与 pattern匹配的最短部分。

    file="data.txt.backup"; echo "${file%.*}"   # 输出: data.txt (删除最短的`.*`,即最后一个`.`及之后)
  • ${parameter%%pattern}​:从 parameter值的末尾删除与 pattern匹配的最长部分。

    file="data.txt.backup"; echo "${file%%.*}"  # 输出: data (删除最长的`.*`,即第一个`.`及之后的所有内容)
  • ${parameter/pattern/string}​:将 parameter值中第一个匹配 pattern的子字符串替换为 string

    str="hello world hello"; echo "${str/hello/hi}" # 输出: hi world hello
  • ${parameter//pattern/string}​:将 parameter值中所有匹配 pattern的子字符串替换为 string

    str="hello world hello"; echo "${str//hello/hi}" # 输出: hi world hi
  • ${parameter/#pattern/string}​:如果 pattern匹配 parameter值的开头,则将其替换为 string

    str="hello world"; echo "${str/#hello/hi}"   # 输出: hi world
    str="world hello"; echo "${str/#hello/hi}"   # 输出: world hello (开头不匹配)
  • ${parameter/%pattern/string}​:如果 pattern匹配 parameter值的末尾,则将其替换为 string

    str="file.txt"; echo "${str/%.txt/.doc}"     # 输出: file.doc
    str="file.txt.backup"; echo "${str/%.txt/.doc}" # 输出: file.txt.backup (末尾不是精确匹配.txt)

3. 获取字符串长度和子字符串

  • ${#parameter}​:扩展为 parameter值的字符长度

    str="hello"; echo "Length: ${#str}"          # 输出: Length: 5
  • ${parameter:offset}​:从 parameter值的第 offset个字符开始(0-based)扩展,直到末尾

    str="0123456789"; echo "${str:3}"           # 输出: 3456789
  • ${parameter:offset:length}​:从 parameter值的第 offset个字符开始(0-based),扩展指定长度的字符。

    str="0123456789"; echo "${str:3:4}"          # 输出: 3456

    注意​:offset可为负数,表示从字符串末尾向前计算。负 offset前必须有一个空格,以避免与 :-混淆。

    str="0123456789"; echo "${str: -4:2}"        # 输出: 67 (从倒数第4个字符开始,取2个)

4. 变量转换与间接引用

  • ${parameter@operator}​:对 parameter的值应用特定的 operator

    • Q: 将值转义为可被 Shell 重用的引用形式。

    • E: 对值中的反斜杠转义序列进行扩展(在某些版本的 Bash 中)。

    var="hello 'world'"; echo "${var@Q}"          # 输出: 'hello '\''world'\'''
  • ${!prefix*}或 ${!prefix@}​:扩展为所有以 prefix开头的变量名,由 IFS的第一个字符分隔。

    echo "${!BASH*}" # 可能输出: BASH BASHOPTS BASHPID ... (所有以BASH开头的变量名)
  • ${!name}​:​间接引用。如果 name是一个变量,且它的值是另一个变量的名称,则 ${!name}扩展为那个变量的值。

    foo="bar"; bar="actual value"; echo "${!foo}" # 输出: actual value

5. 修改大小写 (Bash 4.0+)

  • ${parameter^}​:将 parameter值的第一个字符转换为大写。

  • ${parameter^^}​:将 parameter值的所有字符转换为大写。

  • ${parameter,}​:将 parameter值的第一个字符转换为小写。

  • ${parameter,,}​:将 parameter值的所有字符转换为小写。

    word="hello"; echo "${word^}"                # 输出: Hello
    echo "${word^^}"                             # 输出: HELLO
    WORD="HELLO"; echo "${WORD,}"                # 输出: hELLO
    echo "${WORD,,}"                             # 输出: hello

    注意​:^和 ,在某些上下文中也可以用 ~替代。

✨ 实用技巧与注意事项

  1. 保护变量名​:当变量名后紧跟字母、数字或下划线时,使用 {}是必须的,否则 Bash 会将其视为一个整体变量名。

    var="hello"; echo "${var}world"             # 输出: helloworld
    echo "$varworld"                             # 输出: (空,因为变量`varworld`未设置)
  2. 模式匹配​:在 #%##%%///#%中,pattern遵循 Shell 的通配符模式(glob pattern),而不是正则表达式。*匹配任意字符,?匹配单个字符。

  3. 空值与未设置​:对于 ${parameter:-word}${parameter:=word}${parameter:?word}${parameter:+word},​冒号 :的存在至关重要

    • 有冒号​:检查 parameter是 ​未设置​ 还是 ​为空

    • 无冒号​:​仅检查​ parameter是否 ​未设置​(即使设置为空字符串,也算已设置)。

  4. 数组处理​:许多参数扩展形式也可用于数组。例如 ${#array[@]}获取数组元素个数,${array[@]:offset:length}获取子数组。

  5. 引号的重要性​:为了处理包含空格的字符串或文件名,​总是将参数扩展用双引号引起来是一种好习惯。

    file="file with spaces.txt"
    rm $file    # 可能出错,会被视为三个参数
    rm "$file"  # 正确,是一个参数
  6. 性能考虑​:在可能的情况下,使用 Shell 的内置字符串操作(参数扩展)通常比调用外部命令(如 sedawkcut)更高效。

掌握这些参数扩展技巧能极大提升你编写 Shell 脚本的效率和脚本的灵活性。

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

相关文章:

  • 接口自动化测试之设置断言思路
  • 什么是MIPS架构?RISC-V架构?有什么区别?【超详细初学者教程】
  • 深入Linux内核:IPC资源管理揭秘
  • 从 “对话” 到 “共创”:生成式 AI 如何重塑内容创作全流程,普通人也能掌握的高效工具指南
  • MongoDB 备份与恢复:mongodump 和 mongorestore 实战
  • Qt 的信号signal的参数是否会在内部被拷贝?
  • duilib中CTextUI控件使用技巧与问题总结(CTextUI控件自适应文字宽度特性)
  • 如何正确使用ChatGPT做数学建模比赛——数学建模AI使用技巧
  • 【macOS】垃圾箱中文件无法清理的“含特殊字符文件名”的方法
  • 开发使用mybatis是用混合模式还是全注解模式
  • 陕西凉拌西瓜皮,变废为宝的陕味美味~
  • JavaScript 性能优化实战技术
  • 【GIS图像处理】有哪些SOTA方法可以用于将1.5米分辨率遥感图像超分辨率至0.8米精度的?
  • mysql实例是什么?
  • Midscenejs自然语言写测试用例
  • 基于uni-app的校园综合服务平台开发实战
  • 大模型落地全流程实践:从技术选型到企业级部署
  • 警告:OPENCV_FFMPEG_READ_ATTEMPTS (current value is 4096)
  • flume接收处理器:构建高可用与高性能的数据链路
  • AR-LSAT 推理任务全解析:从逻辑推理到类比推理的挑战
  • Fabarta个人专属智能体赋能媒体:从过载信息到深度可控的创作体系
  • Claude AI 因编写勒索软件和开展勒索活动而被滥用
  • java基础1
  • DevExpress WinForms中文教程:Data Grid - 过滤编辑器
  • 【机器学习学习笔记】pandas基础
  • matlab-神经网络的语音识别
  • SHELL命令pr
  • 【C++】 Vector容器操作全解析
  • OpenHarmony智能语音框架深度拆解:从VAD到唤醒词打造你的AI语音智能体
  • 第8篇c++Expression: (L“Buffer is too small“ 0