![为什么 zsh 不扩展函数“(:a)”中定义的这个 glob](https://linux22.com/image/204229/%E4%B8%BA%E4%BB%80%E4%B9%88%20zsh%20%E4%B8%8D%E6%89%A9%E5%B1%95%E5%87%BD%E6%95%B0%E2%80%9C(%3Aa)%E2%80%9D%E4%B8%AD%E5%AE%9A%E4%B9%89%E7%9A%84%E8%BF%99%E4%B8%AA%20glob.png)
仅当我通过执行 触发全局扩展时,脚本的第二行才有效echo
。我不明白为什么。这是命令及其执行情况以提供一些上下文。
函数定义:
~/ cat ~/.zsh/includes/ascii2gif
ascii2gif () {
setopt extendedglob
input=$(echo ${1}(:a))
_path=${input:h}
input_f=${input:t}
output_f=${${input_f}:r}.gif
cd $_path
nerdctl run --rm -v $_path:/data asciinema/asciicast2gif -s 2 -t solarized-dark $input_f $output_f
}
激活 ascii2gif 函数的函数调试。
~/ typeset -f -t ascii2gif
调试后的函数执行:
~/ ascii2gif ./demo.cast
+ascii2gif:1> input=+ascii2gif:1> echo /Users/b/demo.cast
+ascii2gif:1> input=/Users/b/demo.cast
+ascii2gif:2> _path=/Users/b
+ascii2gif:3> input_f=demo.cast
+ascii2gif:4> output_f=demo.gif
+ascii2gif:5> cd /Users/b
+_direnv_hook:1> trap -- '' SIGINT
+_direnv_hook:2> /Users/b/homebrew/bin//direnv export zsh
+_direnv_hook:2> eval ''
+_direnv_hook:3> trap - SIGINT
+ascii2gif:6> nerdctl run --rm -v /Users/b:/data asciinema/asciicast2gif -s 2 -t solarized-dark demo.cast demo.gif
==> Loading demo.cast...
==> Spawning PhantomJS renderer...
==> Generating frame screenshots...
==> Combining 40 screenshots into GIF file...
==> Done.
我已经尝试了多种变体来尝试强制扩展等input=${~1}(:a)
,但无济于事。有什么建议么?显然,该脚本可以工作,但似乎不是最佳的。
答案1
那是因为你尝试使用的方式修饰符a
这里是用于通配符,并且不会发生通配符(因为通配符通常会产生多个单词,因此它不会发生在需要单个单词的上下文中)。因此,您依赖于命令替换内发生的通配符,然后将结果分配给变量。var=WORD
由于a
修饰符可以用于参数扩展,但应用方式不同,您可以尝试:
input=${1:a}
例如:
% cd /tmp
% foo() { input=${1:a}; typeset -p input; }
% foo some-file
typeset -g input=/tmp/some-file
答案2
/u穆鲁的回答看起来这是解决这个问题的正确方法,但原因是为什么它没有扩展的是文件名生成(通配符)不会发生在标量赋值中(它会发生在数组赋值中,因为通配符 - 一般来说 - 可能会返回多个匹配项):
从man zshoptions
:
GLOB_ASSIGN <C> If this option is set, filename generation (globbing) is per‐ formed on the right hand side of scalar parameter assignments of the form `name=pattern (e.g. `foo=*'). If the result has more than one word the parameter will become an array with those words as arguments. This option is provided for backwards com‐ patibility only: globbing is always performed on the right hand side of array assignments of the form `name=(value)' (e.g. `foo=(*)') and this form is recommended for clarity; with this option set, it is not possible to predict whether the result will be an array or a scalar.
所以
$ zsh -c 'f=${1}(:a); echo $f' zsh file.txt
file.txt(:a)
但
$ zsh -c 'f=(${1}(:a)); echo $f' zsh file.txt
/home/steeldriver/dir/file.txt