Shell 变量是 Shell 脚本中的一个重要组成部分,它们允许你存储和操作数据。以下按章节详细介绍 Shell 的变量。

1. 变量的定义与赋值

Shell 变量的定义和赋值非常简单,只需使用=符号将值赋予变量名:

variable_name=value

注意:

  • 变量名不能有空格,且不能以数字开头。
  • 赋值语句中不能有空格,例如 name = value 是错误的。

示例:

name="John"
age=30

2. 变量的引用

要引用变量的值,需要在变量名前加上$符号:

echo $variable_name

示例:

echo $name   # 输出 "John"
echo $age    # 输出 "30"

注意:

  • 如果你需要在复杂的字符串中引用变量,建议使用花括号将变量名包裹起来以避免歧义:
    echo "Hello, ${name}!"

3. 变量的作用域

Shell 变量有两种作用域:

3.1. 局部变量

默认情况下,所有在当前 Shell 会话中定义的变量都是局部变量,只有在当前 Shell 或脚本中可见,子进程不可访问这些变量。

示例:

foo="local_value"
bash -c 'echo $foo'  # 子 Shell 中不可见,输出为空

3.2. 环境变量

如果你希望某个变量可以被子进程(例如 Shell 脚本中的另一个命令)访问,则需要将其导出为环境变量:

export variable_name

示例:

export PATH="/usr/local/bin:$PATH"
bash -c 'echo $PATH'  # 子 Shell 中可见

4. 特殊变量

Shell 提供了一些预定义的特殊变量,用于获取特定的状态或信息:

  • $0: 当前脚本或命令的名称
  • $1, $2, ..., $n: 传递给脚本或函数的参数
  • $#: 参数的个数
  • $@: 传递给脚本或函数的所有参数(作为独立的字符串处理)
  • $*: 传递给脚本或函数的所有参数(作为单个字符串处理)
  • $?: 上一个命令的退出状态
  • $$: 当前 Shell 进程的 PID
  • $!: 最近执行的后台命令的 PID

示例:

#!/bin/bash
echo "Script name: $0"
echo "First argument: $1"
echo "Second argument: $2"
echo "Total arguments: $#"

5. 位置变量与参数传递

在执行脚本时,可以通过命令行向脚本传递参数,这些参数通过位置变量(如 $1, $2 等)获取。

./script.sh arg1 arg2

在脚本中:

echo "Argument 1: $1"
echo "Argument 2: $2"

6. 变量的操作

Shell 提供了很多操作变量的方式,常见的有字符串操作、算术操作和数组操作。

6.1. 字符串操作

可以通过以下方式操作字符串:

  • 获取字符串长度:${#variable}

    str="Hello"
    echo ${#str}  # 输出 5
  • 子字符串提取:${variable:position:length}

    echo ${str:1:3}  # 输出 "ell"
  • 替换子字符串:${variable/pattern/replacement}

    str="apple orange apple"
    echo ${str/apple/banana}  # 替换第一个出现的 "apple""banana"
    echo ${str//apple/banana} # 替换所有出现的 "apple""banana"

6.2. 算术操作

Shell 允许使用 let$(( ))expr 来进行简单的算术运算:

a=5
b=3

let sum=a+b
echo $sum  # 输出 8

echo $((a * b))  # 输出 15

6.3. 数组操作

Bash 支持一维数组,数组中的元素可以通过索引访问:

arr=(10 20 30)
echo ${arr[0]}  # 输出 10
echo ${arr[@]}  # 输出所有元素
echo ${#arr[@]}  # 输出数组长度

7. 变量的删除

可以通过 unset 命令删除变量:

unset variable_name

删除后,变量将不再有效。

示例:

unset name
echo $name  # 不会输出任何内容

8. 只读变量

通过 readonly 命令将变量设置为只读,一旦设置,该变量将无法再修改:

readonly variable_name

示例:

readonly pi=3.1415
pi=3.14  # 报错:无法修改只读变量

9. 变量的默认值

使用默认值机制,可以确保变量在未定义时具有一个默认值:

  • 如果变量未定义,则使用默认值:${variable:-default}
  • 如果变量未定义或为空,则使用默认值:${variable:=default}
  • 如果变量未定义,则输出错误并退出:${variable:?error_message}
  • 如果变量已定义,则替换其值:${variable:+new_value}

示例:

name=${name:-"Default Name"}  # 如果 $name 未定义,赋值为 "Default Name"

10. 小结

Shell 变量是 Shell 编程的基础工具,通过变量,可以有效地存储、传递、操作数据。熟练掌握 Shell 变量的定义、作用域、操作和一些特殊的处理方式,可以极大提高编写 Shell 脚本的效率。

在 Shell 编程中,##%% 是字符串操作中非常有用的符号,它们用于模式匹配和字符串截取。它们属于参数扩展的一部分,允许我们根据指定的模式修改或操作变量的值。现在,我来补充这部分内容。

11. 字符串模式匹配操作

Shell 提供了一些模式匹配符来进行字符串的删除操作,主要包括 ###%%%。这些符号用于匹配和截取字符串的前缀或后缀。

11.1. 删除字符串的前缀

  • #:从变量开头删除最短匹配的字符串。
  • ##:从变量开头删除最长匹配的字符串。

示例:

filename="path/to/my/file.txt"

# 删除最短匹配的前缀
echo ${filename#*/}  # 输出 "to/my/file.txt"

# 删除最长匹配的前缀
echo ${filename##*/}  # 输出 "file.txt"

解释:

  • #*/:删除最短匹配的前缀,这里删除的是第一个 / 及其之前的部分。
  • ##*/:删除最长匹配的前缀,这里删除的是最后一个 / 及其之前的部分。

11.2. 删除字符串的后缀

  • %:从变量末尾删除最短匹配的字符串。
  • %%:从变量末尾删除最长匹配的字符串。

示例:

filename="path/to/my/file.txt"

# 删除最短匹配的后缀
echo ${filename%.*}  # 输出 "path/to/my/file"

# 删除最长匹配的后缀
echo ${filename%%.*}  # 输出 "path/to/my/file"

解释:

  • %.*:删除最短匹配的后缀,这里删除的是第一个 . 及其之后的部分。
  • %%.*:删除最长匹配的后缀,这里删除的是最后一个 . 及其之后的部分。

12. 字符串替换操作

除了简单的删除前缀和后缀,Shell 还提供了一些符号用于字符串替换。主要是 ///

  • ${variable/pattern/replacement}:替换第一个匹配到的子字符串。
  • ${variable//pattern/replacement}:替换所有匹配到的子字符串。

示例:

string="I love apples and apples are great"

# 替换第一个出现的 "apples"
echo ${string/apples/oranges}  # 输出 "I love oranges and apples are great"

# 替换所有出现的 "apples"
echo ${string//apples/oranges}  # 输出 "I love oranges and oranges are great"

13. 默认值机制和变量检查

Shell 中可以通过参数扩展来设置变量的默认值或者检查变量是否已定义。

  • ${variable:-default}:如果变量未定义或为空,则使用默认值。
  • ${variable:=default}:如果变量未定义或为空,则赋值为默认值,并将默认值赋给变量。
  • ${variable:+replacement}:如果变量已定义且不为空,则返回 replacement,否则返回空字符串。
  • ${variable:?error_message}:如果变量未定义或为空,则输出错误信息并退出脚本。

示例:

# 如果 name 未定义或为空,使用默认值 "John"
echo ${name:-"John"}  # 如果 $name 未定义,输出 "John"

# 如果 name 未定义或为空,赋值为 "John" 并输出
echo ${name:="John"}

# 如果 name 已定义且不为空,输出 "defined"
echo ${name:+defined}

# 如果 name 未定义或为空,输出错误信息并退出脚本
echo ${name:?"Error: name is not defined"}

14. 小结

在 Shell 编程中,#%/: 等符号提供了灵活的字符串操作方法,帮助我们进行模式匹配、字符串删除、替换和默认值设置。这些操作符可以提高 Shell 脚本的灵活性和可维护性,尤其是在处理文件路径、参数检查和字符串替换时非常有用。

作者:严锋  创建时间:2023-12-18 12:46
最后编辑:严锋  更新时间:2025-05-09 15:48