首页 > 解决方案 > 在 Bash 中,每一段 "${BASH_SOURCE:-${(%):-%x}}" 是什么意思

问题描述

最近我想知道在 Bash 中获取当前正在运行的脚本/文件的路径的最佳方法。

我找到了很多答案。特别是:

"${BASH_SOURCE:-${(%):-%x}}"

我记得当时决定这是满足我需求的最佳解决方案。现在我试图记住为什么。我知道一些片段是什么意思,但不是全部。即使有我所知道的,我也无法把它们放在一起来理解它。有用。但为什么?

我在网络上的任何地方(包括搜索它的一部分)所做的一切努力都失败了,所以我找不到我最初找到它的地方。

谁能告诉我每件作品的含义(甚至可能建议我为什么选择这个而不是其他答案)?

谢谢!


第二天更新:@rici 的精彩回答(和评论)解释了一切,包括我为什么选择它。

看来我选择了整个表达式是为了使我使用它的源文件能够在 bash 和 zsh 中可靠地使用——这是一个目标。使用双重替换,整个表达式在任一 shell 中都得到相同的答案。

解释了为什么我对 bash 中的 ${(%):-%x} 部分没有任何意义(或通过谷歌找到任何有意义的东西),因为......嗯......它在 bash 中没有多大意义,大声笑,因为它是用于 zsh 的。出于这个原因,我现在为此添加了一个 zsh 标签。


一个小时后的第二次更新,以防这对任何人都有帮助:我现在已经找到了这个:

${BASH_SOURCE[0]} 在 zsh 中的等价物?

...这是我${(%):-%x}最初得到的地方,最值得注意的是这个具体的答案:

https://stackoverflow.com/a/28336473/4516124

标签: bashzsh

解决方案


这个特殊的表达式试图在 bash 和 zsh 中提供相同的结果:当前运行脚本的文件路径。

在 bash 中,

"${BASH_SOURCE:-${(%):-%x}}"

意思是“$BASH_SOURCE如果它存在并且不为空,否则${(%):-%x}”。只要您在$BASH_SOURCE定义为非空值的上下文中使用它,否则${(%):-%x}将永远不会使用无效的替换,并且 bash 不会抱怨它。[注1]

有关详细说明,$BASH_SOURCE请参阅@mklement0 的出色回答

现在,在 zsh 中,变量$BASH_SOURCE通常没有定义(尽管我想它可能是从父级导出的),所以替换确实发生了,然后 zsh 用扩展替换它${(%):-%x}。Bash 用户可能会发现它更加神秘,但我们可以将其分解如下:

  1. ${...:-...} 与 bash 中的含义相同:如果左手部分为空或未定义,则使用右手部分。与 bash 不同,zsh 允许左侧部分完全为空,而不仅仅是值为空的变量。{:-foo}复杂的书写方式也是如此foo

  2. ${(flags)...}导致在扩展上评估指定的标志。在这种情况下,我们有 flag %,这意味着应该对参数扩展进行“提示扩展”。[笔记2]

  3. 如果没有处理标志,我们就剩下{:-%x}; 如第 1 点所示,这相当于 string %x。但是该(%)标志会触发%x. 而在zsh提示扩展中,%x是--等待它--当前正在执行的脚本文件的名字。

简而言之,在 zsh 中,${(%):-%x}意味着(几乎)与 bash 中的完全相同$BASH_SOURCE。因此,${BASH_SOURCE:-${(%):-%x}}扩展为 bash 和 zsh 中的当前脚本源文件。


笔记

  1. $BASH_SOURCE另一方面,如果未定义或为空,则会产生“错误替换”。正如我们稍后将看到的,${(flags)...}它是一种 zsh 特定的语法,但这并不是 bash 抱怨它的原因。bash,它看起来像一个%不存在的参数的后缀删除(运算符)$(。它抱怨,因为$(它不是一个有效的参数名称。

    为了比较,考虑非常相似但有效的替换${#%):-%x}。与 具有相同的值$#,因为$#不以 . 结尾):-%x。这种解析可能对人眼来说是令人惊讶的,但 bash 认为它是平淡无奇的。

  2. Zsh 与 bash 一样,具有高度可定制的提示,在提示变量之一中使用特殊的转义序列。(Posix 标准提示变量是$PS1,$PS2$PS4;bash 和 zsh 都提供了其他几个变量。)Bash 提供了一些特殊的反斜杠序列\u例如,是当前用户名),并且还允许在扩展提示时解释任意参数扩展。Zsh 也有多种转义序列,但%用作转义字符(%n是当前用户名),如果prompt_subst设置了 shell 选项,则允许参数扩展。

    请注意,您通常不能像在 bash 中那样zsh通过简单的设置来试验提示$PS1,因为大多数zsh安装都使用“提示主题”。启用提示主题后,您需要创建自己的主题以更改提示字符串,因为主题设置会在每个命令之前自动应用。


推荐阅读