使用^作为外壳元字符


19

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

grep -q ^local0 /etc/syslog.conf

在审查过程中,一位同事建议^local0引用该词,因为^在Bourne外壳中意为“烟斗”。对此声明感到惊讶,我试图查找提及此内容的任何参考。我在互联网上没有发现任何暗示这是问题的信息。

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

> bsh
$ ls ^ wc
      23      23     183
$ ls | wc
      23      23     183

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

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


1
我知道这^是zsh和正则表达式空间中的否定字符。作为单独的注释,通常建议在grep表达式中使用单引号,以实现跨shell的可移植性。
mkc

bourne shell有很多奇怪的行为,我们仍然可以在现代shell代码中看到解决方法,例如[ x"$foo" = x"bar" ]
jordanm

bsh不是伯恩壳牌。该名称仅在AIX上的Bourne Shell中被滥用。bsh而是我在1984年由H.Berhold AG在UNOS(第一个UNIX克隆)上引入的shell。请注意,AIX在1984
。– schily

Answers:


21

^字符作为的代名词|日期从后面汤普森壳。它们在Unix v4中同时引入,并在手册页中一起提到。Sven Mascheck提到,^“可能是[出于早期在仅使用大写字母的终端上的便利而引入]”,其中键入|“有些痛苦”

汤普森(Thompson)shell早已一去不复返,但其后继者伯恩(Bourne)Shell保留了相同的语法(即使其手册页仅提及|)。

ash,bash和ksh之类的后继壳仅被理解|为管道字符。您将不会在开源的unix变体上找到实际的Bourne shell,因为很长时间以来,还没有开源的Bourne shell版本。(我认为OpenSolaris包含一个,但是到那时它还没有被其他地方采用,因为到那时它已被较新的实现所淘汰。)

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

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

^为了清晰起见,我建议仍然以正则表达式引用。不管脚本中出现什么字符,都要在脚本中引用正则表达式。

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


谢谢,2003年以来的整个TUHS线程都很有启发性。
Greg Hewgill

为了完整起见,您可能想在它是重定向操作符,/ 是串联操作符或csh / tcsh / bash / zsh作为历史记录扩展(当它是命令行的第一个字符)时^特别提及。fishrces
斯特凡Chazelas


3

是的,OpenSolaris包含Bourne Shell源,但该源不可移植。

可在此处schily-*.tar.bz2档案库中找到Bourne Shell源代码的维护和高度可移植的版本。

这是来源中的相关部分cmd.c

/* 
* ^ is a relic from the days of UPPER CASE ONLY tty model 33s 
*/ 
if ((t = item(TRUE)) != 0 && (wdval == '^' || wdval == '|')) 

您会看到,这与特定的外壳(例如Thompson外壳)无关,而是与1970年代仍然只有大写字母的端子有关。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.