是否可以在 ZSH 中动态定义函数?

D. *_*ggs 4 zsh metaprogramming function function-definition

我想在ZSH中动态定义一系列函数。

例如:

#!/bin/zsh
for action in status start stop restart; do
     $action() {
         systemctl $action $*
     }
done
Run Code Online (Sandbox Code Playgroud)

然而,这会产生四个相同的函数,它们都调用最后一个参数:

$ status libvirtd
==== AUTHENTICATING FOR org.freedesktop.systemd1.manage-units ====
Authentication is required to restart 'libvirtd.service'.
...
Run Code Online (Sandbox Code Playgroud)

有没有办法像这样动态定义这些函数?

Nad*_*'El 10

Yes, it's actually very easy:

for action in status start stop restart
do
    $action() {
        systemctl $0 "$@"
    }
done
Run Code Online (Sandbox Code Playgroud)

The key point here is the use of $0. The problem with your original solution was that the "$action" inside the function's definition was not expanded during the definition, so in all four functions it just referred to the last value of this variable. So instead of trying to get it to work with ugly trickery using eval (as suggested in another solution), the nicest solution is just to use $0... In shell script, $0 expands to the name of the current script, and in shell functions, it expends to the name of the current function. Which happens to be exactly what you wanted here!

Note also how I used "$@" (the quotes are important) instead of $*. This works correctly with quoted arguments with whitespace, which $* ruins.

最后,对于这个用例,您可以使用“别名”而不是函数,一切都会简单得多:

for action in status start stop restart
do
    alias $action="systemctl $action"
done
Run Code Online (Sandbox Code Playgroud)