使用 ^ 作为 shell 元字符

Gre*_*ill 19 shell pipe history portability bourne-shell

我今天写了一个小脚本,其中包含

grep -q ^local0 /etc/syslog.conf
Run Code Online (Sandbox Code Playgroud)

在审查期间,一位同事建议^local0引用,因为^在 Bourne shell 中表示“管道”。对这个说法感到惊讶,我试图追踪任何提到这一点的参考资料。我在互联网上发现的任何内容都没有表明这是一个问题。

但是,事实证明,bshAIX 7 上的(声称是 Bourne shell)的实现实际上具有以下行为:

> bsh
$ ls ^ wc
      23      23     183
$ ls | wc
      23      23     183
Run Code Online (Sandbox Code Playgroud)

我尝试过的其他“Bourne shell”实现^都没有这种行为(也就是说,根本不被认为是 shell 元字符)。我sh在 CentOS(真正的 bash)和shFreeBSD(不是 bash)上尝试过。我没有很多其他系统可以尝试。

这种行为是预期的吗?哪些 shell 被认为^是管道元字符?

Gil*_*il' 21

^作为同义词的字符|可以追溯到Thompson shell。它们是在 Unix v4 中同时引入的,并在手册页中一起提到。Sven Mascheck提到^“可能[引入] 是为了方便早期的大写终端”,其中打字|“有点痛苦”

Thompson shell 早已不复存在,但它的后继者Bourne shell保留了相同的语法(即使它的手册页只提到了|)。

诸如 ash、bash 和 ksh 之类的后继 shell 只能理解|为管道字符。您不会在开源 unix 变体上找到实际的 Bourne shell,因为很长一段时间没有 Bourne shell 的开源版本。(我认为 OpenSolaris 包括一个,但它没有被其他地方采用,因为到那时它已经被较新的实现所淘汰了很久)。

单一Unix规范没有提到^作为一个特殊的字符,这实际上意味着POSIX炮弹应该解释它literally¹。我认为从来没有完全符合 POSIX 的 Bourne shell 变体(只有独立的实现)。

^extendedglob启用该选项时,在 zsh 中是特殊的,但在其 sh 兼容模式下则不然。在默认模式下,它在很多方面都与 POSIX 有所不同。

^无论如何,为了清楚起见,我建议在正则表达式中引用。在脚本中引用正则表达式,而不管其中出现什么字符。

¹除了作为通配符模式中括号表达式的第一个字符外, where!是标准否定字符,但实现也可以以^相同的方式解释。