【Linux基础及shell脚本】Shell脚本中变量的使用

1. Shell变量基础

1.1 什么是变量

在编程语言中,变量是一个存储值的地方。你可以把变量想象成是一个存储盒,你可以在里面放任何东西,当你需要的时候,就可以通过变量名取出来。变量可以包含字母,数字和下划线,但是变量名必须以字母或下划线开始。

在 Shell 中,变量没有数据类型。一个 Shell 变量的值是一个字符串,不论这个字符串是否是数字,字符,甚至是字符串中包含多余的空格或其他特殊字符。

1.2 如何在Shell中定义和使用变量

在 Shell 中,你可以用等号 = 来定义变量。注意,等号两边不能有空格,这是 Shell 语法规定的。下面是一个定义变量的例子:

name="John Doe"

在这个例子中,我们定义了一个叫做 name 的变量,其值为 “John Doe”。

使用变量的时候,需要在变量名前面加上 $ 符号。例如,我们可以打印出变量 name 的值:

echo $name

这行命令会输出 “John Doe”。请注意,当你引用一个未定义的变量时,Shell 会把它当作是空字符串。

你也可以用 unset 命令来删除一个变量:

unset name

执行以上命令后,变量 name 就被删除了。如果你试图打印它的值,你将得不到任何输出。

2. Shell环境变量

2.1 什么是环境变量

环境变量是 Linux 和其他 Unix-like 操作系统中的一个重要组成部分。它们是存储系统状态或 Shell 会话信息的特殊变量。例如,HOME 环境变量存储了当前用户的主目录路径,PATH 环境变量存储了系统在执行命令时应当查找二进制文件的路径列表。

环境变量在 Shell 会话和它们的子进程之间是共享的。也就是说,你在父 Shell 中定义的环境变量可以在它所启动的所有子 Shell 中使用。

2.2 环境变量与普通变量的区别

环境变量与普通变量的主要区别在于它们的可见性和生命周期。

  • 可见性:普通变量只在当前 Shell 会话中有效,子 Shell 不会继承这些变量。而环境变量可以在父 Shell 和所有子 Shell 之间共享。

  • 生命周期:普通变量的生命周期只在当前 Shell 会话期间,当会话结束时,变量就会消失。但是环境变量在定义后,除非明确删除,否则会一直存在。

2.3 如何查看、设置和删除环境变量

查看环境变量可以使用 envprintenv 命令。例如:

printenv PATH

这个命令会打印出 PATH 环境变量的值。

设置环境变量,可以使用 export 命令。例如:

export VARNAME="value"

这个命令会创建一个名为 VARNAME 的环境变量,其值为 “value”。这个变量将在当前 Shell 会话及其子会话中有效。

删除环境变量,可以使用 unset 命令。例如:

unset VARNAME

这个命令会删除 VARNAME 环境变量。需要注意的是,这个命令只会删除当前 Shell 会话中的变量,它不会影响其他 Shell 会话中的相同名字的变量。

3. Shell位置参数

3.1 位置参数是什么

在 Shell 脚本中,位置参数是一种特殊的变量,它们代表了命令行参数的值。例如,如果你的脚本名为 myscript.sh,你运行 ./myscript.sh arg1 arg2 arg3,那么 arg1arg2arg3 就是位置参数。

Shell 会自动将这些参数赋值给特殊变量 $1$2$3,依此类推。在这个例子中,$1 的值就是 arg1$2 的值就是 arg2$3 的值就是 arg3

3.2 如何在脚本中使用位置参数

在 Shell 脚本中,你可以通过 $1$2$3 等变量直接使用位置参数。这些变量代表了你在执行脚本时传递的参数。

例如,假设你有一个脚本 myscript.sh,它的内容如下:

#!/bin/bash
echo "第一个参数是: $1"
echo "第二个参数是: $2"
echo "第三个参数是: $3"

然后你运行 ./myscript.sh apple banana cherry,脚本的输出将会是:

第一个参数是: apple
第二个参数是: banana
第三个参数是: cherry

3.3 位置参数的实际应用示例

位置参数在许多场景中都非常有用。例如,你可能有一个脚本,它需要用户输入一个或多个文件名作为参数,然后对这些文件进行操作。你可以用位置参数来获取这些文件名。

以下是一个简单的示例脚本,它接受一个文件名作为参数,然后打印出这个文件的行数:

#!/bin/bash
if [ -f "$1" ]; then
    echo "$1 的行数为:"
    wc -l "$1"
else
    echo "文件 $1 不存在"
fi

在这个脚本中,$1 代表用户输入的文件名。-f 测试检查文件是否存在,wc -l 命令计算文件的行数。

4. Shell特殊变量

4.1 Shell中的特殊变量介绍

Shell 有一些特殊变量,它们有特殊的含义和功能。以下是一些常见的 Shell 特殊变量:

  • $0:这个变量的值是当前脚本的文件名。
  • $#:这个变量的值是传递给脚本的位置参数的个数。
  • $*:这个变量是所有位置参数的列表。如果你用双引号包围它,"$*",那么所有位置参数将被当作一个字符串。
  • $@:这个变量也是所有位置参数的列表。但是,如果你用双引号包围它,"$@",那么每个位置参数都被当作单独的字符串。
  • $$:这个变量的值是当前 Shell 进程的进程 ID(PID)。
  • $?:这个变量的值是最后一个执行的命令的退出状态。如果命令成功执行,退出状态是 0。如果命令失败,退出状态是非零值。

4.2 特殊变量的功能和用途

特殊变量在 Shell 脚本中有很多用途。以下是一些示例:

  • 使用 $0 可以在脚本中打印出它自己的文件名。这在调试和日志记录中很有用。

  • 使用 $# 可以在脚本中检查用户是否提供了正确数量的参数。例如,如果你的脚本需要两个参数,你可以使用 if [ $# -ne 2 ] 检查用户是否提供了两个参数。

  • 使用 $*$@ 可以在脚本中迭代所有的位置参数。$*$@ 的行为略有不同,特别是在你用双引号包围它们的时候。

  • 使用 $$ 可以在脚本中获取当前 Shell 进程的 PID。这在你需要创建唯一的临时文件名或者检查进程是否正在运行时很有用。

  • 使用 $? 可以在脚本中检查命令是否成功执行。这在错误处理和调试中很有用。

5. Shell变量操作

5.1 如何对Shell变量进行操作

在 Shell 中,你可以对变量进行各种操作,例如赋值,字符串连接,子字符串提取,和计算长度等等。

  • 赋值:你可以使用等号 = 给变量赋值,例如 var="Hello, World!"

  • 字符串连接:你可以使用双引号 "..." 将多个字符串或变量连接在一起,例如 greeting="Hello, $name!"

  • 子字符串提取:你可以使用 ${var:offset:length} 提取子字符串,其中 offset 是起始位置(从 0 开始计数),length 是子字符串的长度。

  • 计算长度:你可以使用 ${#var} 计算字符串的长度。

5.2 字符串截取、长度计算等实例演示

以下是一些示例:

  • 字符串连接:

    name="John"
    greeting="Hello, $name!"
    echo $greeting
    

    这个脚本会输出 “Hello, John!”。

  • 子字符串提取:

    str="Hello, World!"
    echo ${str:7:5}
    

    这个脚本会输出 “World”。子字符串的起始位置是 7,长度是 5。

  • 计算长度:

    str="Hello, World!"
    echo ${
          
          #str}
    

    这个脚本会输出 “13”,这是字符串 “Hello, World!” 的长度。

6. 变量的作用域

6.1 全局变量和局部变量的区别

在 Shell 中,变量默认是全局的。这意味着你在脚本的任何地方定义的变量都可以在脚本的任何地方使用。这包括在函数内部。

然而,你也可以定义局部变量。局部变量只在它们被定义的函数内部有效。你可以使用 local 关键字在函数内部定义局部变量。一旦函数返回,局部变量就会被销毁。

全局变量和局部变量的主要区别在于它们的作用域:

  • 全局变量的作用域是整个脚本。这意味着你可以在脚本的任何地方访问全局变量。

  • 局部变量的作用域仅限于它们被定义的函数。这意味着你只能在定义局部变量的函数内部访问这些变量。

6.2 在函数中使用变量的正确方式

当你在函数中使用变量时,应该尽量使用局部变量,除非你确实需要在函数外部访问这个变量。使用局部变量可以帮助你避免命名冲突,并使你的函数更容易理解和测试。

以下是一个示例,展示了如何在函数中定义和使用局部变量:

function greet {
    
    
    local name=$1
    echo "Hello, $name!"
}

greet "John"

在这个函数中,name 是一个局部变量。$1 是函数的第一个参数。这个函数将打印 “Hello, John!”。

如果你试图在函数外部访问 name,你将得到一个空值,因为 name 是局部的,只在 greet 函数内部有效。

猜你喜欢

转载自blog.csdn.net/weixin_52665939/article/details/131525868