菜鸟科技网

Ubuntu命令如何替换?

命令替换是一种强大的 shell 功能,它允许你执行一个命令,然后将其输出结果捕获,并插入到另一个命令的原始位置

Ubuntu命令如何替换?-图1
(图片来源网络,侵删)

这就像把一个命令的执行结果“粘贴”到另一个命令的行里。


核心语法

命令替换有两种主要的语法,它们在现代 shell 中都可用,但反引号版本有一些缺点。

语法 1:反引号 (Backticks) - 传统方式

这是最古老的语法,但在所有 shell 中都可用。

command1 `command2`
  • command2:这部分将被 shell 执行。
  • command2 的输出结果:会替换掉 command2 的位置,command1 再使用这个结果来执行。

示例: 假设你想要创建一个以当前日期和时间命名的日志文件。

Ubuntu命令如何替换?-图2
(图片来源网络,侵删)
# date 命令会输出类似 "Mon Oct 24 10:30:00 CST 2025" 的内容
touch `date +%Y-%m-%d`.log

执行过程:

  1. Shell 先执行 date +%Y-%m-%d
  2. 假设输出是 2025-10-24
  3. Shell 将原始命令行替换为 touch 2025-10-24.log
  4. 然后执行这个新的命令,创建一个名为 2025-10-24.log 的文件。

语法 2: - 现代、推荐的方式

这是目前最推荐、最安全、最强大的方式,几乎所有现代 shell(如 Bash, Zsh)都支持它。

command1 $(command2)

示例: 同样创建一个以日期命名的日志文件。

touch $(date +%Y-%m-%d).log

执行过程与反引号版本完全相同。

Ubuntu命令如何替换?-图3
(图片来源网络,侵删)

为什么要优先使用 而不是反引号?

尽管两种语法功能相似,但 在多个方面都优于反引号。

  1. 嵌套能力 可以无限嵌套,而反引号在嵌套时会变得非常混乱和难以阅读。

    使用 的嵌套示例:

    # 获取当前用户的主目录,并在其中创建一个文件夹
    mkdir $(echo $(echo $HOME)/new_folder)
    # 等价于: mkdir /home/username/new_folder

    使用反引号的嵌套示例:

    # 这种写法非常不直观,容易出错
    mkdir `echo \`echo $HOME\`/new_folder`

    你需要用反斜杠 \ 来转义内层的反引号,可读性极差。

  2. 可读性 更清晰地表明“这是一个命令的执行结果”,而反引号很容易和单引号混淆,尤其是在某些字体中。

  3. 错误处理 如果反引号中的命令执行失败,整个命令替换可能会以难以预料的方式失败。 的错误处理机制通常更清晰。


实用示例

命令替换在日常系统管理中非常常见。

示例 1:遍历命令的输出

这是最常见的用法之一,例如遍历文件列表。

# 列出当前目录下的所有 .txt 文件,并逐个删除它们
for file in $(ls *.txt); do
  echo "Deleting file: $file"
  rm "$file"
done

注意:当文件名中包含空格时,for file in $(...) 这种方式会出问题,因为它会按空格和换行符进行分割,更稳健的写法是使用 find 命令结合 while 循环,或者使用 globstar 选项 (shopt -s globstar)。

示例 2:将命令结果作为参数传递给另一个命令

# 获取当前系统上所有用户列表,并统计用户数量
echo "There are $(wc -l < /etc/passwd) users on this system."
  • < /etc/passwd 是将文件内容作为标准输入传给 wc -l
  • 捕获了 wc -l 的输出(一个数字)。
  • echo 命令将这个数字插入到句子中。

示例 3:变量赋值

你可以将命令的输出赋值给一个变量。

# 获取当前工作目录
current_dir=$(pwd)
# 获取系统的内核版本
kernel_version=$(uname -r)
echo "You are in: $current_dir"
echo "Your kernel version is: $kernel_version"

最佳实践:给变量赋值时,尽量使用 ,因为它更清晰。

示例 4:在条件判断中使用

# 检查 /etc/hosts 文件是否存在,如果存在则显示其行数
if [ -f /etc/hosts ]; then
  echo "The /etc/hosts file has $(wc -l < /etc/hosts) lines."
else
  echo "The /etc/hosts file does not exist."
fi

进阶用法:readarraymapfile (处理多行输出)

当命令的输出包含多行内容,并且你希望将每一行作为一个独立的元素存入数组时,readarray (或其别名 mapfile) 是一个非常强大的工具。

场景: 你想获取所有 .sh 文件名,并对它们进行操作。

# mapfile 是 readarray 的一个更易读的别名
mapfile -t sh_files < <(find . -maxdepth 1 -name "*.sh")
# -t 选项会移除每行末尾的换行符
# < <(...) 是 "进程替换",它将 find 命令的输出像一个文件一样传递给 mapfile
echo "Found ${#sh_files[@]} shell scripts:"
# 遍历数组并打印每个文件名
for script in "${sh_files[@]}"; do
  echo "  - $script"
done

这种方式比 for file in $(find ...) 要健壮得多,因为它能正确处理文件名中的空格和特殊字符。


特性 反引号 `
语法 `command` | $(command)
嵌套 困难,需要转义 (```) 容易,清晰
可读性 较差,易与单引号混淆 优秀,语义清晰
现代性 传统,兼容旧 shell 现代,推荐用法
推荐度 ⭐ (仅在需要兼容极旧环境时使用) ⭐⭐⭐⭐⭐ (强烈推荐)

核心要点:

  1. 命令替换就是执行一个命令,用其输出替换掉命令本身。
  2. 优先使用 语法,它更安全、更强大、更易读。
  3. 主要用途包括:变量赋值、参数传递、循环遍历
  4. 对于处理多行输出并存储为数组的情况,请使用 mapfilereadarray
分享:
扫描分享到社交APP
上一篇
下一篇