我正在尝试创建我的第一个zsh完成脚本,在本例中为命令netcfg。
Lame听起来可能听起来我已经陷入了第一道障碍,免责声明,我知道如何粗暴地做到这一点,但我寻求“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
似乎这不起作用,我敢肯定必须有一些聪明的方法来做到这一点,分成一个数组并得到最后一部分,但正如我所说,我完全没有这个。
感谢任何建议。
答案 0 :(得分: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' *(.))"}
答案 1 :(得分:2)
克里斯·约翰森的答案充满了关于zsh的有用信息,但是没有提到在这种特殊情况下更简单的解决方案:
echo /etc/network.d/*(:t)
这是使用t
历史记录修饰符作为 glob限定符。
答案 2 :(得分:1)
感谢您的建议,我们已经完成了对ZSH的更多阅读并在几天后回到问题中,我想我有一个非常简洁的解决方案,我想为您的利益分享。
echo $ {$(print /etc/network.d / *(。)):t}
答案 3 :(得分: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