Bash 字符串处理:basename 与变量截取详解

在 Shell 脚本编程中,处理文件名和路径是家常便饭。basename 命令和 Bash 的变量截取功能是两个强大的工具,它们能帮助你高效、灵活地处理字符串。了解它们的用法和注意事项,可以让你写出更健壮、更通用的脚本。


basename:提取文件名

basename 是一个独立的命令,专门用于从完整路径中提取文件名。它的核心作用就是移除路径中的目录部分

# 假设一个完整的文件路径
FULL_PATH="/home/user/documents/report.2023.pdf"

# 使用 basename 提取文件名
FILENAME=$(basename "$FULL_PATH")

echo "$FILENAME"
# 输出: report.2023.pdf

注意: 最佳实践是在变量 $FULL_PATH 周围加上双引号 "",以防止路径中包含空格或特殊字符时出现问题。


Bash 变量截取:操作字符串

Bash 的变量截取是 Shell 内置的功能,它提供了更细粒度的控制,可以对字符串进行删除、提取和替换。我们主要通过 #%: 等符号来操作。

1. 删除前缀和后缀

  • 删除最短前缀(#)和最长前缀(##

    • # 只删除匹配到的最短部分,而 ## 则会删除最长的匹配部分。
    PATH="/home/user/file.txt"
    echo ${PATH#*/}    # 输出: home/user/file.txt (最短匹配,只删除了开头的 '/')
    echo ${PATH##*/}   # 输出: file.txt (最长匹配,删除了直到最后一个 '/' 的所有内容)
    
  • 删除最短后缀(%)和最长后缀(%%

    • % 只删除匹配到的最短部分(通常用于删除文件扩展名),%% 则会删除最长的匹配部分。
    FILENAME="archive.tar.gz"
    echo ${FILENAME%.*}   # 输出: archive.tar (最短匹配,只删除了 ".gz")
    echo ${FILENAME%%.*}  # 输出: archive (最长匹配,删除了 ".tar.gz")
    

2. 提取子字符串

这个功能类似于其他编程语言中的 substring 方法,它允许你根据位置和长度来提取字符串的一部分。

  • 语法:${变量:起始位置:长度}

    STRING="abcdefg"
    echo ${STRING:1:3}  # 输出: bcd (从索引1开始,提取3个字符)
    
  • 负数索引的特殊用法

    这是最容易出错但又非常有用的特性。负数索引表示从字符串的末尾开始计算。

    STRING="abcdefg"
    echo ${STRING: -3:2}  # 输出: ef (从倒数第三个字符开始,提取2个字符)
    

    注意: 使用负数索引时,冒号 : 和负号 - 之间必须有一个空格。如果没有空格,Bash 会将 ${STRING:-3} 解释为另一种参数扩展(如果变量为空则使用默认值),导致截取功能失效。这是初学者最容易犯的错误。

在前面的总结中,确实没有详细介绍 Bash 变量截取的字符串替换功能。这是一个同样强大且常用的特性,主要通过 / 符号来实现。


Bash 变量截取:字符串替换

字符串替换允许你查找变量中的特定模式,并用新的字符串替换它。这个功能分为两种主要形式:首次替换全局替换

1. 首次替换

这个功能只会替换变量中第一次出现的匹配项。

  • 语法:${变量/查找/替换}

    STRING="hello world, hello again"
    
    # 只替换第一个 "hello"
    echo ${STRING/hello/hi}  # 输出: hi world, hello again
    

2. 全局替换

如果你想替换变量中所有匹配项,就需要使用双斜杠 //

  • 语法:${变量//查找/替换}

    STRING="hello world, hello again"
    
    # 替换所有 "hello"
    echo ${STRING//hello/hi}  # 输出: hi world, hi again
    

这个功能在处理配置文件的路径、标准化文件名或快速清理字符串时非常有用。例如,你可以用它来批量替换文件名中的空格:

FILENAME="my video file.mp4"

# 将所有空格替换为下划线
NEW_FILENAME=${FILENAME// /_}

echo "$NEW_FILENAME"  # 输出: my_video_file.mp4

总结:何时使用谁?

  • basename:当你的目标是简单地从完整路径中获取文件名时,使用 basename 是最直接和安全的选择。
  • 变量截取:当你需要更精细地操作字符串,比如删除特定的扩展名、提取文件名中某一部分或根据位置截取时,变量截取功能是不可或缺的。

掌握这两个工具,你就能更高效地编写处理文件和路径的 Bash 脚本,让你的代码更简洁、更强大。