本文介绍了在Bash中,每一段“${BASH_SOURCE:-${(%):-%x}}"是什么意思?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Recently I wanted to know the best way to get the path to the currently running script/file in Bash.

我找到了很多答案.特别是其中之一:

I found a lot of answers. In particular one was:

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

我记得当时我认为这是满足我需求的最佳解决方案.现在我正在努力记住为什么.我知道一些片段的意思,但不是全部.即使有了我所知道的,我也不能把它们放在一起来理解它.有用.但为什么?

I remember deciding at the time that this was the best solution for my needs. Now I'm trying to remember why. I know what some of the pieces mean, but not all. And even with what I do know I can't put it all together to make any sense of it. It works. But why?

我为在网络上的任何地方找到这个特定代码所做的一切努力(包括搜索它的一部分)都失败了,所以我无法找到最初找到它的地方.

Every effort I've made to find this specific code anywhere on the web (including searching for bits of it) has failed, so I can't find where I found it originally.

谁能告诉我每个部分的含义(甚至可以说明为什么我可能会选择这个而不是其他答案)?

Can anyone tell me what each piece means (and perhaps even suggest why I might have chosen this over other answers)?

谢谢!

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

UPDATE next day: great answer (and comments) from @rici which explain everything, including why I chose it.

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

It seems I chose this entire expression to enable the sourced files I'm using it in to be used reliably in both bash and zsh - which was and is a goal. With the dual substitutions, the entire expression gets the same answer in either shell.

解释了为什么我无法理解(或通过谷歌找到任何合理的)bash 中的 ${(%):-%x} 部分,因为......好吧......它没有多大意义在 bash 中是有意义的,哈哈,因为它是针对 zsh 的.出于这个原因,我现在为此添加了一个 zsh 标签.

Explains why I couldn't make any sense of (or find anything sensible via google for) the ${(%):-%x} part in bash because... well... it doesn't make much sense in bash, lol, since it's for zsh. I'm now adding a zsh tag to this for that reason.

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

Second UPDATE an hour later, in case this helps anyone: I've now tracked down this:

${BASH_SOURCE[0]} 在 zsh 中等效?

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

... which is where I got the ${(%):-%x} from originally, most notably this specific answer:

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

推荐答案

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

This peculiar expression is attempting to provide the same result in bash and in zsh: the filepath of the currently running script.

在 bash 中,

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

表示$BASH_SOURCE,如果它存在且不为空,否则为${(%):-%x}".只要您在 $BASH_SOURCE 定义为非空值的上下文中使用它,否则无效的替换 ${(%):-%x}永远不会被使用,bash 也不会抱怨它.[注1]

means "$BASH_SOURCE if it exists and is not empty and otherwise ${(%):-%x}". As long as you use this in a context in which $BASH_SOURCE is defined as a non-empty value, the otherwise invalid substitution ${(%):-%x} will never be used and bash won't complain about it. [Note 1]

有关$BASH_SOURCE 的详细说明,请参阅@mklement0 的优秀答案.

For a detailed explanation of $BASH_SOURCE please see this excellent answer by @mklement0.

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

Now, in zsh the variable $BASH_SOURCE is normally not defined (although I suppose it might be exported from the parent), so the substitution does happen and zsh then replaces it with the expansion ${(%):-%x}. Bash users might find that one even more mysterious, but we can take it apart as follows:

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

  1. ${...:-...} means the same thing as in bash: use the right hand part if the left hand part is empty or undefined. Unlike bash, zsh allows the left-hand part to be completely empty, not just a variable whose value is empty. So {:-foo} is a complicated way of writing foo.

${(flags)...} 导致在扩展时评估指定的标志.在这种情况下,我们有标志 %,这意味着提示扩展"应该做参数扩展.[注2]

${(flags)...} causes the specified flags to be evaluated on the expansion. In this case, we have the flag %, which means that "prompt expansion" should be done on the parameter expansion. [Note 2]

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

Without the flags are handled, we're left with {:-%x}; as indicated in point 1, this is equivalent to the string %x. But the (%) flag triggers prompt expansion of %x. And in zsh prompt expansion, %x is -- wait for it -- the name of the currently executing script file.

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

In short, in zsh, ${(%):-%x} means (almost) exactly the same thing as $BASH_SOURCE does in bash. And therefore, ${BASH_SOURCE:-${(%):-%x}} expands to the current script source file in both bash and zsh.

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

  1. If $BASH_SOURCE is undefined or empty, on the other hand, this will produce a "bad substitution". As we'll see in a moment, ${(flags)...} is a zsh-specific syntax, but that's not why bash complains about it. To bash, it looks like a suffix deletion (the % operator) of the non-existent parameter $(. And it complains because $( is not a valid parameter name.

为了比较,请考虑非常相似但有效的替换 ${#%):-%x}.它与 $# 具有相同的值,因为 $# 不以 ):-%x 结尾.这种解析对人的眼睛来说可能令人惊讶,但 bash 却把它看得很清楚.

For comparison, consider the very similar but valid substitution ${#%):-%x}. That has the same value as $#, because $# doesn't end with ):-%x. That parse might be surprising to human eyes, but bash sees it plain as day.

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

Zsh, like bash, has extremely customisable prompts using special escape sequences in one of the prompt variables. (Posix standard prompt variables are $PS1, $PS2 and $PS4; both bash and zsh offer several others.) Bash offers some special backslash sequences (\u is the current username, for example), and also allows arbitrary parameter expansions to be interpreted when the prompt is expanded. Zsh also has a variety of escape sequences, but uses % as an escape character (%n is the current username), and allows parameter expansions if the prompt_subst shell option is set.

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

Note that you usually can't experiment with zsh prompts by simply setting $PS1, as you can in bash, because most zsh installations use "prompt themes". Once prompt themes are enabled, you need to create your own theme in order to change the prompt strings, because the theme settings are automatically applied before every command.

这篇关于在Bash中,每一段“${BASH_SOURCE:-${(%):-%x}}"是什么意思?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-19 13:37