zsh文件名为globbling/substitution

iri*_*ava 2 zsh glob autocomplete

我正在尝试创建我的第一个zsh完成脚本,在本例中为命令netcfg.

Lame听起来可能听起来我已经陷入了第一道障碍,免责声明,我知道如何粗暴地做到这一点,但是我寻求"ZSH WAY"来做到这一点.

我需要在/ etc/networking中列出文件,但只列出文件,而不是目录组件,所以我做了以下操作.

echo $(ls /etc/network.d/*(.))

/etc/network.d/ethernet-dhcp /etc/network.d/wireless-wpa-config
Run Code Online (Sandbox Code Playgroud)

我想要的是:

ethernet-dhcp wireless-wpa-config
Run Code Online (Sandbox Code Playgroud)

所以我试着(原谅我的天真):

echo ${(s/*\/)$(ls /etc/network.d/*(.))}

/etc/network.d/ethernet-dhcp /etc/network.d/wireless-wpa-config
Run Code Online (Sandbox Code Playgroud)

似乎这不起作用,我敢肯定必须有一些聪明的方法来做到这一点,分成一个数组并得到最后一部分,但正如我所说,我完全是noob在这.

任何建议都感激不尽.

Chr*_*sen 7

一般说明:无需使用ls生成文件名.你也可以使用 echo some*glob.但是如果你想保护可能的嵌入式换行符,即使这是一个坏主意.下面的第一个示例直接进入数组以保护嵌入式换行符.第二个使用printf生成NUL终止数据,以便在不使用变量的情况下完成相同的操作.

如果您愿意使用变量,这很容易做到:

typeset -a entries
entries=(/etc/network.d/*(.)) # generate the list
echo ${entries#/etc/network.d/}  # strip the prefix from each one
Run Code Online (Sandbox Code Playgroud)

你也可以在没有变量的情况下做到这一点,但是隔离单个条目的额外东西有点难看:

# From the inside, to the outside:
# * glob the entries
#   * NUL terminate them into a single string
# * split at NUL
#   * strip the prefix from each one
echo ${${(0)"$(printf '%s\0' /etc/network.d/*(.))"}#/etc/network.d/}
Run Code Online (Sandbox Code Playgroud)

或者,如果您打算使用子shell(即前面示例中的命令替换),只需cd到目录,这样它就不是glob扩展的一部分(另外,您不必重复目录名称):

echo ${(0)"$(cd /etc/network.d && printf '%s\0' *(.))"}
Run Code Online (Sandbox Code Playgroud)