【问题标题】:zsh ${var##$pat} parameter expansion with pattern var containing globszsh ${var##$pat} 参数扩展,带有包含 glob 的模式 var
【发布时间】:2021-08-29 07:42:10
【问题描述】:

${var##$pat} 参数扩展中,zsh 似乎不支持 variable 模式中的全局变量:

$ zsh -c 'pat=/*; var=/etc/; echo "$var $pat"; echo "${var##$pat}"'
/etc/ /*
/etc/
# sh result: empty

但是,如果 $pat 不包含 *,zsh 和 sh 的行为类似:

$ zsh -c 'pat=/; var=/etc/; echo "$var $pat"; echo "${var##$pat}"'
/etc/ /
etc/
# sh result: same

zsh --emulate sh 当然会给出与 sh 兼容的结果。但是如果我想留在 zsh 仿真中,是否有任何 setopt 选项可以改变这种行为?我已经(简要地)查看了文档,但我真的找不到造成这种差异的原因。

【问题讨论】:

  • 在 zsh 中,一个简单的 echo $pat 也不会扩展该模式,因此如果在您在此处提供的上下文中默认发生这种扩展,那就太奇怪了。 zsh 在变量中激活通配符的方式是,即echo $~pat
  • 我的情况是我正在尝试编写一个可移植的脚本(我在问题中没有提到)。
  • 便携用什么方式?跨越不同的zsh版本?请注意,zsh 在其历史上发生了相当大的变化。
  • 在现代机器上便携
  • 鉴于大多数语言(尤其是 bash 和 zsh)在我所知道的几乎所有平台上都可用,您可以坚持使用其中一种,只是不要假设您将拥有最新版本可用的。如果您真的对可移植性感到偏执(例如,它应该在您无权安装任何东西的机器上运行),您可以在 POSIX shell 中开发并完全忽略 zsh; sh 真的应该随处可用。

标签: zsh glob parameter-expansion


【解决方案1】:

zsh 中,变量内容只会被视为一个模式,如果你 使用${~spec} 扩展或(非常广泛,因此有点危险)GLOB_SUBST 选项来要求:

pat=/*t
var=/etc/
print "${var##$pat}"
#=> /etc/
print "${var##$~pat}"
#=> c/
setopt glob_subst
print "${var##$pat}"
#=> c/

这在zshexpn 手册页的字符串替换扩展部分${name/pattern/repl} 中有描述。

【讨论】:

  • 我明白了; setopt GLOB_SUBST 是否也会生成 $pat glob 文件名(在 ${var##$pat} 中)?
  • 我的意思是,从简单的测试来看似乎并非如此,但有模棱两可的地方需要应对
  • 我找不到有关其工作原理的明确手动参考,但zshexpn 手册页中的Rules 部分表明文件名扩展晚于其他扩展,因此变量将被视为需要字符串模式的上下文中的字符串模式,然后在允许的上下文中作为全局模式。因此,例如v=/etc/*; p=/*c; print ${~v##$~p} 中的每个波浪线都会产生不同的效果。注意:规则部分确实有一个(笑话)警告阅读它们会导致脑损伤,所以要小心:-)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-02-22
  • 2020-10-06
  • 2015-10-21
  • 2018-10-20
  • 2012-09-12
  • 1970-01-01
相关资源
最近更新 更多