Categories: Shell

Bash脚本内置变量详解

Bash 中,内置变量是那些由 shell 内部有意设置的变量,以便用户使用。这些变量也被称为特殊参数。内置变量主要负责存储与 shell 或环境相关的信息。在编写 Bash 脚本时,使用这些变量很有帮助,因为它们的角色是提供访问和操作执行 shell 或脚本的重要信息。

Bash 中的内置变量

下表简要概述了 Bash 中的 9 个内置变量。

内置变量 描述
$0 当前脚本的文件名。
$1…$9 存储前 9 个参数名称的位置参数
$ 当前 shell 的进程 id。
$# 提供给脚本的参数数量。
$* 存储所有命令行参数。
$@ 以数组形式存储参数列表。
$? 指定最后一条命令或最近一次执行过程的退出状态。
$! 显示最后一条后台命令的 id。
$- 显示当前 bash shell 中使用的选项集。

$0 – 脚本的名称

特殊的 Bash 变量 $0 用于保存脚本的名称。让我们尝试一个例子:
示例:

#!/bin/bash
echo "I am running the script $0 "

$1-$9 – 脚本的参数

我们可以使用特殊变量 $1 到 $9 来引用传递给脚本的参数。
示例:

#!/bin/bash
echo argument 1 is $1
echo argument 2 is $2
echo argument 3 is $3
echo argument 9 is $9

运行此脚本为:

    ./splVar2.sh a b c d e f g h i

$0 存储脚本的名称。$1 保存第一个参数,即 "a",以此类推。因此,最后的值 "i" 将存在于 $9 变量中。

$# – 参数的数量

要获取参数的数量,我们通常会使用循环。我们遍历传递给脚本的所有参数,并每次递增计数 1。相反,我们只需要使用 $# 变量。

示例:

#!/bin/bash
echo "Count of arguments $#"

现在让我们使用以下命令运行此脚本:

    ./splVar3.sh a b c d e f g

为了获取计数,我们向脚本提供了 7 个参数。脚本使用特殊变量 $# 打印计数为 7。

$*$@ – 所有参数

Bash 使用 $* 和 $@ 来展开完整的位置参数列表 $1 $2 $3。这简化了传递和处理位置参数,无论是在脚本还是函数中。如果不使用双引号,$@ 和 $* 的效果是相同的。

示例:

#!/bin/bash
echo "----------------Using $@----------------"
for input in $@
do
 echo "$input "
done
echo "----------------Using $*----------------"
for input in $*
do
 echo "$input "
done

现在让我们使用以下命令运行此脚本:

    ./splVar4.sh a b c d

当我们执行时,$@ 以及 $* 展开了脚本可用的参数。在每次迭代中,它都会挑选参数并在终端上打印。这省去了我们逐个挑选位置参数 $1,$2… $n 的麻烦。

$– 进程识别号 (PID)

$ 变量用于存储当前 shell 的进程 ID (PID)。这是操作系统分配给每个运行进程的唯一标识符。我们需要做的就是在我们的脚本中使用 $,每当我们想获取 PID 时。
示例:

echo $
echo "Making an entry" >> myfile-$.txt

如我们所知,PID 是一个唯一的数字,我们在脚本中使用 $ 变量来生成一个唯一的文件名。

$? – 最后一条命令的退出状态

当我们想要检查最后一条命令执行的状态时,我们必须依赖 $? 变量。返回的输出是一个整数。0 表示成功,非 0 表示失败。
示例:

在第一种情况下,我们执行 pwd 命令来获取工作目录的路径。由于这个命令执行成功,$? 返回 0。在下一个情况中,由于 abc 不是一个有效的命令,所以这种情况下返回的整数是一个非零数。我们经常使用这个特性来开发条件以处理文件。

$! – 最后一条后台命令的 PID

Bash 有特殊变量 $! 用于获取最后一条执行的后台命令的 PID。我们可以在后台运行任何命令。我们需要在末尾附加 & 符号。这个命令然后在一个子 shell 中执行,并且 shell 继续执行下一个命令,而不等待后台命令完成。
示例:

sleep 10 &
echo "PID of the command in the background is $!"


由于 & 符号被附加到它上,所以 sleep 命令在后台执行。shell 立即返回并执行下一个命令,该命令使用 $! 变量打印后台命令的 PID。当有多个后台命令时,$! 变量由最后执行的后台命令的 PID 修改。

$- – 当前选项标志

特殊变量 $- 显示 shell 的当前选项集。这些选项控制 shell 的行为。常用的选项有:

  • i – 使 shell 以交互模式运行。
  • e – 如果任何命令以非零状态退出,使 shell 立即退出。
  • x – 使 shell 在执行每个命令之前将其打印到终端。
  • u – 使 shell 将未设置的变量视为错误并退出。
    示例:
    !/bin/bash
    echo "Current shell options: $-"
    set -e
    echo "When e is set"
    echo "Current shell options: $-"
    set +e
    echo "When e is unset"
    echo "Current shell options: $-"


我们最初使用 $- 获取当前的 shell 选项。
然后使用 set -e 命令启用 e 选项。这使得如果任何命令以非零状态退出,shell 将立即退出。我们再次使用 $- 获取更新的 shell 选项。
最后我们使用 set +e 命令禁用 e 选项,并打印最新的 shell 选项。

$_ – 最近的参数

特殊变量 $_ 包含上一条执行命令的最后一个参数。
示例:

我们首先执行 echo 命令打印 "Good day"。下一条命令 echo $_ 打印 $_ 变量持有的值。它包含最近执行的命令的最后一个参数。因此我们在终端上第二次看到 "Hello, world!"。
$_ 只包含上一条命令的最后一个参数,而不是整个命令本身。如果前一个命令有多个参数,$_ 只包含最后一个参数。

示例脚本

在这一部分,我们将举一个例子,将我们迄今为止看到的每一个变量都用起来。

!/bin/bash
usage()
{
 echo "Usage: $0 <file1> [<file2> ... <fileN>]"
}
if [ "$#" -lt 1 ]
then
 echo "No file specified."
 usage
 exit 1
fi
echo "Number of arguments to the script=$# and first argument is $1"
for file in "$@"
do
 if [ ! -f "$file" ]
 then
 echo "[ERROR] File $file doesn't exist"
 continue
 else
 currentDate= date +%d-%m-%y 
 currentTime= date +%H-%M 
 cp file ${file}_$_${currentDate}_${currentTime}
 RC=$?
 if [[ ${RC} -eq 0 ]]
 then
 echo "Copied $file to ${file}_$_${currentDate}_${currentTime}"
 echo "Its first line is: "
 head -1 ${file}_$_${currentDate}_${currentTime}
 fi
 fi
done
echo "Current shell options: $-"

  1. usage 函数显示如何运行脚本。我们使用了 $0 变量来显示脚本的名称。
  2. 我们使用 $# 计算脚本可用的参数数量。如果少于 1,表示没有提供参数。在这种情况下,我们调用 usage 方法并终止脚本。
  3. 如果参数多于 1,使用 $1 变量显示计数和第一个参数,
  4. 然后我们使用 $@ 一次读取所有参数。
  5. 对于每个条目,我们检查指定的输入是否是一个文件。如果不是文件,我们显示错误消息并使用 continue 语句跳到下一个迭代。
  6. 如果是文件,我们从 Bash 的 date 命令中提取当前日期和时间。
  7. 然后我们使用 $ 创建一个具有唯一名称的文件备份:file__
  8. 然后我们使用 $? 验证 cp 命令的退出状态。如果它的数值是零,表示命令成功。
  9. 最后我们显示成功复制的消息。
  10. 对于 for 循环中的下一个条目,我们重复此操作。
  11. 在循环结束后,我们使用特殊的 bash 变量 $- 显示当前的 shell 选项。
5.0
02
Expect脚本详解
如何在Bash中输出多行字符串
嘻嘻

嘻嘻IT: 笔者是一个工作七八年的程序猿老鸟,从事涉及的技术栈主要包括PHP、Linux、Devops等,喜欢研究新技术,尝试新技术,提升技术自动化和开发效率,致力于write less,do more! 技术每年都会层出不穷,领域划分的越来越细,不可能学习所有的东西,保持对技术的好奇心,理解技术中核心思想,做一个有深度,有思想的开发!

Recent Posts

PHP Composer如何安装?

PHP Composer是PH…

24小时 ago

MacOS上Missing xcrun的问题

在使用MacOS进行编程或开发…

1天 ago

CodeGeeX是一款基于大模型的全能AI编程助手

CodeGeeX是一个面向开发…

1天 ago

MySQL覆盖索引详解

在数据库性能优化中,索引是一个…

1天 ago

后端程序员必备:SQL优化的20条建议

SQL优化查询对于后端程序员来…

1天 ago