如何制作 zsh 函数,让我可以输入不带引号的字符串,但它会用引号解释?

如何制作 zsh 函数,让我可以输入不带引号的字符串,但它会用引号解释?

我想创建一个运行如下的函数:

youtube-dl -f 'bestvideo[ext=mp4]+bestaudio[ext=m4a]/best[ext=mp4]/best' "https://www.youtube.com/watch?v=_OBlgSz8sSM"

目前,在 .zshrc 中,我一直在尝试

downloadyoutube(){
    youtube-dl -f 'bestvideo[ext=mp4]+bestaudio[ext=m4a]/best[ext=mp4]/best' "$1"

但它仍然希望我在调用它时在 URL 周围添加引号。

相反,我想跑

downloadyoutube https://www.youtube.com/watch?v=_OBlgSz8sSM

不带引号。

并不是

downloadyoutube "https://www.youtube.com/watch?v=_OBlgSz8sSM"

有没有办法做到这一点?

答案1

正如拘萨罗南达(Kusalananda)所说,noglob这是要走的路;您可以按原样定义您的函数,然后使用aliasinclude noglob

downloadyoutube(){
  youtube-dl -f 'bestvideo[ext=mp4]+bestaudio[ext=m4a]/best[ext=mp4]/best' "$1"
}
alias downloadyoutube="noglob downloadyoutube"

不管怎样,你试图用这些论点做什么是没有意义的:youtube-dl默认它已经很多年了;阅读当前man页面!


我想强调的是,库萨拉南达是对的:

  1. 您甚至'不仅需要"在这里,以免您希望一些特殊字符成为问题,
  2. 即使关闭通配符也无助于防止事件/重定向字符;由于每个 Youtube URL 都会包含&,您最好将 shell 配置为自动将&字符串中粘贴的内容(而不是在行尾)替换为\&;我的 zsh 会自动执行此操作,我认为这应该归咎于 oh-my-zsh。

答案2

您可能遇到的问题(您实际上没有提及)是,zsh如果文件名通配模式与任何名称都不匹配,则默认情况下 shell 会发出错误:

$ downloadyoutube https://www.youtube.com/watch?v=_OBlgSz8sSM
zsh: no matches found: https://www.youtube.com/watch?v=_OBlgSz8sSM

这里的 URL 包含字符?,它是一个通配符。这会提示 shell 使用 URL 作为模式执行文件名匹配。找不到匹配项,因此 shell 会抱怨,甚至不会尝试调用您的函数。

bash如果failglob设置了 shell 选项, shell中也会有类似的行为:

$ shopt -s failglob
$ downloadyoutube https://www.youtube.com/watch?v=_OBlgSz8sSM
bash: no match: https://www.youtube.com/watch?v=_OBlgSz8sSM

NOGLOB您可以通过设置shell 选项来阻止 shell 使用 URL 作为通配模式setopt NOGLOB。这将关闭当前 shell 会话中的通配符,直到您使用unsetopt NOGLOB.

您还可以在函数调用前加上 前缀,这具有为单个命令noglob设置 shell 选项的效果:NOGLOB

noglob downloadyoutube https://www.youtube.com/watch?v=_OBlgSz8sSM

然而,最明智的方法是在调用函数时使用单引号引用 URL。 URL 很可能包含其他shell 特有的字符不是&例如,通配字符,它引入了后台作业。&即使文件名通配关闭,如果不引用它,带有 in 的 URL将无法使用。

关闭通配符也不会禁用大括号扩展 ( {...}) 或子 shell ( (...)),这可能会在 URL 中意外发生。

相关内容