3

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

听起来很蹩脚,我已经坚持了第一个障碍,免责声明,我知道如何粗略地做到这一点,但是我寻求“ZSH WAY”来做到这一点。

我需要列出 /etc/networking 中的文件,但只列出文件,而不是目录组件,所以我执行以下操作。

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

/etc/network.d/ethernet-dhcp /etc/network.d/wireless-wpa-config

我想要的是:

ethernet-dhcp wireless-wpa-config

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

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

/etc/network.d/ethernet-dhcp /etc/network.d/wireless-wpa-config

似乎这不起作用,我确信必须有一些聪明的方法通过拆分成一个数组并获取最后一部分来做到这一点,但正如我所说,我对此完全是菜鸟。

感激地收到任何建议。

4

4 回答 4

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

您也可以在没有变量的情况下执行此操作,但是隔离各个条目的额外内容有点难看:

# 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/}

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

echo ${(0)"$(cd /etc/network.d && printf '%s\0' *(.))"}
于 2010-07-05T10:10:05.480 回答
3

Chris Johnsen 的回答充满了关于 zsh 的有用信息,但是它没有提到在这种特殊情况下更简单的解决方案:

echo /etc/network.d/*(:t)

这是使用t 历史修饰符作为全局限定符

于 2010-07-16T22:00:12.640 回答
1

感谢您的建议,已经对 ZSH 做了更多阅读并在几天后回到了这个问题,我想我有一个非常简洁的解决方案,我想分享给您。

回声 ${$(打印 /etc/network.d/*(.)):t}

于 2010-07-09T13:22:26.847 回答
0

我习惯于看到basename(1)剥离目录组件;此外,您可以使用echo /etc/network/*来获取文件列表,而无需运行外部ls程序。(运行外部程序可能会比您想要的更慢完成速度;我没有找到用于 basename 的 zsh-builtin,但这并不意味着没有。)

以下是我希望对您有所帮助的内容:

haig% for f in /etc/network/* ; do basename $f ; done
if-down.d
if-post-down.d
if-pre-up.d
if-up.d
interfaces
于 2010-07-05T09:48:26.487 回答