带有 glob * 的 Zsh grep 不起作用

带有 glob * 的 Zsh grep 不起作用

同样的命令在 bash 中运行良好

git show --pretty="" --name-only HEAD |  grep -i .*py
zsh: no matches found: .*py

猛击

git show --pretty="" --name-only HEAD  |grep -i .*py
api/client.py

尝试了各种选项,例如使用 退出,传递 -E setopt +o nomatch。

到目前为止什么都没有起作用。

答案1

是关于文件名扩展这发生在 shell 运行之前。发生这种情况的原因是命令中grep有一个未加引号且未转义的星号 ( )。这种星号是 shell 所特有的。*

当您尝试运行grep .*py并且没有匹配的文件时.*py(注意,.*py在这种情况下不被视为正则表达式,点不是特殊的),基本上会发生两件事:

  • POSIX 行为是 shellgrep使用文字.*py作为参数运行。这就是您想要的。这就是 POSIX shell ( sh) 和兼容 shell 的行为方式。

  • 非 POSIX 行为是 shell 检测到不匹配,打印类似以下内容no matches found: .*py,并且不运行grep 根本。这是 Zsh 的默认行为。(为了比较:在 Bash 中,您可以通过 切换到此行为shopt -s failglob。)

如果存在匹配项(在任何 shell 中),例如名为 的文件等,.copy则将被替换为一个或多个单词作为名称,并且会看到它们,而不是文字字符串。该命令会执行您不想要的操作(比较.foo.py.*pygrep.*py我的这个答案)。即使与 匹配,您也不想进行文件名扩展.*py。用引号括住字符串以抑制文件名扩展。在这种情况下,*仅引用或转义就足够了。所有这些都应该有效:

grep -i '.*py'
grep -i ".*py"
grep -i .'*'py
grep -i .\*py

我更喜欢引用整个论点。在某些情况下,其他可能性更有用,知道有多种方法会很好。

相关内容