不能使用/bin/zsh编译csharp程序,但是/bin/bash可以



我的环境

OSX 10.11.6
zsh 5.0.8 (x86_64-apple-darwin15.0)
GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin15)
Mono C# compiler version 4.0.5.0

test.cs

class Test {
        public static void Main() {
                System.Console.WriteLine("hello, world");
        }
}

test.sh

#! /bin/bash
mcs -recurse:*.cs

我可以用/test.sh编译test.cs

但是如果我把test.sh改为

#! /bin/zsh
mcs -recurse:*.cs

错误显示

./test.sh:3: no matches found: -recurse:*.cs

那么,为什么我不能使用zsh?

zsh试图将该单词中的*扩展为文件glob,但失败并引发错误。

bash也做同样的事情,但默认情况下,它只是忽略globbing失败并保持单词完整(因此mcs看到了它期望的参数)。

shopt -s failglob添加到脚本的顶部(对于bash),它也将失败。

引用mcs的参数中的*可以避免这种情况。

mcs -recurse:'*.cs'

因为字符串-recurse:*.cs包含一个未加引号的*,所以大多数shell会尝试将其视为glob模式,并将其扩展为一个或多个匹配的文件名。

zsh中的默认行为是将没有匹配项的模式视为错误,而不是将该模式视为文字字符串。如果启用failglob选项,则可以在bash中看到相同的行为。

$ echo foo*
foo*
$ shopt -s failglob
$ echo foo*
bash: no match: foo*

zsh中,引用以下模式:

#! /bin/zsh
mcs -recurse:"*.cs"

关闭NOMATCH选项,

#! /bin/zsh
setopt NO_NOMATCH
mcs -recurse:*.cs

或者使用zsh命令修饰符:

#! /bin/zsh
noglob mcs -recurse:*.cs

在命令mcs -recurse:*.cs中,*旨在作为参数的文字部分传递给mcs,但它作为路径名扩展的通配符对所有常见Unix外壳(bashzshtcsh和其他)也有意义。因此,如果工作目录中有一个名为-recurse:oops.cs的文件,您的命令可能会让您大吃一惊。

当没有文件与给定模式匹配时,shell的默认行为会产生差异。默认情况下,bash会回到猜测*是字面意思,这实际上就是你的意思。另一方面,zsh表现出更传统的由于未能匹配模式而失败的行为。通过打开failglob选项,也可以诱导bash表现出这种行为。

最好的解决方案是通过引用参数来解决歧义,或者至少转义其中的*bashzsh都应该很好地处理这个版本,而不需要任何特殊选项:

mcs -recurse:*.cs

相关内容

  • 没有找到相关文章

最新更新