在sh中,"${0%/*}"和"${0##*/}"是什么意思?

7

以下是来自brew命令的摘录。

BREW_FILE_DIRECTORY=$(chdir "${0%/*}" && pwd -P)
export HOMEBREW_BREW_FILE="$BREW_FILE_DIRECTORY/${0##*/}"

在Shell中,${0%/*}${0##*/}分别代表什么意思?
2个回答

13

这些是shell中的参数展开:

  • ${var%/*} - 删除最后一个/之后的所有内容。
  • ${var##*/} - 删除最后一个/之前的所有内容。

由于您在脚本中,$0指代的是脚本本身的名称。

总的来说,这将返回您正在运行的脚本的路径或名称。因此,您可以这样做:

BREW_FILE_DIRECTORY=$(chdir <path_of_script> && pwd -P)
export HOMEBREW_BREW_FILE="$BREW_FILE_DIRECTORY/<script_name>"

测试

$ r="hello/how/are/you"
$ echo ${r%/*}
hello/how/are
$ echo ${r##*/}
you

根据上面提到的链接(编辑版本以使它们更短):

${parameter##word}

这个单词被扩展为一个模式,就像文件名扩展一样。如果该模式与参数的扩展值的开头匹配,则扩展的结果是删除具有最长匹配模式(“##”情况)的参数的扩展值。如果参数是“@”或“*”,则模式删除操作依次应用于每个位置参数,并且扩展是结果列表。

${parameter%word}

这个单词被扩展为一个模式,就像文件名扩展一样。如果该模式与参数的扩展值的结尾部分匹配,则扩展的结果是删除具有最短匹配模式(“%”情况)的参数的值。如果参数是“@”或“*”,则模式删除操作依次应用于每个位置参数,并且扩展是结果列表。

关于$0本身,请参见Bash参考手册-> 6.1调用bash

如果在选项处理后仍有参数,并且未提供-c或-s选项,则假定第一个参数是包含shell命令的文件名(请参见Shell脚本)。以这种方式调用Bash时,$0设置为文件的名称,并将位置参数设置为其余参数。 Bash从该文件中读取和执行命令,然后退出。


5

这些是字符串操作。您可以参考这个文档

${string%substring}  # Deletes shortest match of $substring from back of $string.
${string##substring} # Deletes longest match of $substring from front of $string.

有了这个,我们就可以解释运算符在您的代码中的作用了。
${0%/*}

假设$0是一个文件名,使用该命令将会返回该文件所在的目录。它的工作方式与dirname命令相同。
${0##*/}

假设$0是一个文件名,它将给出不带前导路径的文件名。它的工作方式与basename命令相同。


不错!我猜basename比这个参数扩展容易得多。 - fedorqui
@fedorqui 我同意使用 dirname/basename 可以增加可读性。另一方面,参数扩展不需要生成额外的进程。看起来 Homebrew 开发人员很在意毫秒级别的性能.. :) - hek2mgl

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接