2019年8月14日 星期三

Linux Shell元字符、引用符、转义符

1.Linux Shell元字符
使用键盘可以键入字母,数字,和一些其他字符,例如标点符号和算数符号。另外,还可以使用<Space>,<Tab>和<Return>键生成空格,制表符及新行字符。
综合来讲,我们称这些字母和数字为字母数字符(alphanumeric character)。使用字母数字字符比较直接,键入希望键入的,并且所见及所得。但是,当使用shell时,还有许多其他字符有用特殊的含义。我们称这样字符为元字符(Metacharacter),您需要明白它们的工作方式。
在前面讲过通过分号将各条命令分隔开,可以在同一个命令行上输入多条命令。因为分号对shell拥有特殊含义,所以它就是一个元字符。

一个更抽象的例子就是,当按下<Space>,<Tab>和<Return>键时,也使用了元字符,空格和制表符用作分隔命令不同部分的空白符,而新行字符用作一行结束的标记。
下面准备列举所有的元字符,但是没有必要现在就能全部理解它们。后面将一个接一个的解释它们。现在,要看到它们时知道它们是元字符就可以。
例如,如果您准备输入下述命令,shell将会注意到分号,并把您键入的的内容解释成两条命令:

echo The search path is $PATH; the shell is $SHELL.

但是,如果我们知道分号就是元字符,可以采用下述方式告诉shell不用管它: 

echo “The search path is $PATH; the shell is $SHELL

当我们以这种方式保护元字符时,我们就说“引用了”元字符。
下面这个表是一个完整的元字符表。
字符英文名称Unix绰号
&ampersand(和号)1.0
apostrophe(撇号)1.5
*asterisk(星号)1.7
@at sign(at符号)3.2
`backquote(反引号)6.6
\backslash(反斜线)7.9
{}brace brackets(花括号)20.8
^circumflex(音调符号)插入记号
:colon(冒号)
,comma(逗号)
$dollar sign (美元符号)美元
<Return>enter、return(回车)新行
=equal sign(等号)等号
!exclamation mark(感叹号)bang
>greater-than sign (大于符号)大于
-hyphen(连字符)、minus sign(减号)虚线、减号
<less-than sign(小于号)小于
#number sign(序数符号)hash、pound
()parentheses(圆括号)
%percent sign(百分比符号)百分比
.period(点号)
+plus sign(加号)
?question mark(问号)
"quotation mark(引号)双引号
/slash(斜线)正斜线
 <Space>space(空格)
[ ]square brackets(方括号)方括号
 <Tab>tab(制表符)
~tilde(波浪号)
_underscore(下划线)
|vertical bar(竖线)管道

本列表列举了Unix中使用的全部非字母数字字符。作为Unix传统的一部分,大多数字符都有绰号,在讨论它们时会使用。例如,感叹号称为“bang”,$TERM读作“dollar term”,等等。
在shell中,许多非字母数字字符都拥有特殊含义。这些字符都是元字符。本表示范了所有的元字符,以及相应的Unix绰号。最终,您将学会使用每个元字符的精确准则。注意花花括号有两种不同的使用方式。

2. Linux Shell引用和转义符
有时候,可能希望按字面上的含义解释元字符,而不使用其特殊的含义。例如,将分号作为分号使用,而不是一个命令分隔符。或者可能希望不按管道使用|(竖线)。在这些情况中,必须告诉shell按字面意义解释字符。这样做时,可以称其为引用字符。
字符的引用方法有3种:使用反斜线,使用一堆单引号或者使用双引号。
引用元字符最直接的方法就是在元字符前面放一个反斜线(\)。这就告诉shell忽略反斜线之后的字符的任何特殊含义。例如:

echo It is warm and suny \; come over and visit

在这个例子中,我们咋;(分号)字符前面放了一个反斜线。如果没有这个反斜线,那么shell将把分号解释成一个元字符,从而假定您输入了两条独立的命令:echo和come。当然,这将生成错误。

提示:
当希望引用单个字符是,一定要使用反斜线(\),而不是常规的斜线(/)。常规的斜线拥有完全不同的作用。它在路径名中使用。

当使用反斜线引用单个字符时,我们称反斜线为“转义字符(escape character)”。这是一个重要的概念。
之前讨论过运行级别时提到了模式的概念。具体而言,当计算机系统,程序或者设备可能是若干种状态之一时,我们使用术语模式表示特定的状态。Unix或者Linux系统可以引导到单用户模式或者多用户模式。与此类似,在讲述vi文本编辑器时,您会发现,在任何时候,vi或者出于输入模式,或者处于命令模式。
当程序位于一种特定模式,而我们将它修改到另一种模式时,称这是由一种模式转义到另一种模式。当通过按下特定键修改模式时,称该特定键为转义字符。当对shell键入命令时,反斜线就是一个转义字符,因为它告诉shell从一种模式(注意元字符)改变到另一种模式(不用注意元字符)。大家需要记住转义字符的思想,因为会经常遇见它。
在Unix中,单词“escape”有两种使用方法。最常见的就是我们所讨论的从一种模式转移到另一种模式。例如,当使用vi文本编辑器时,按下<Esc>键就可以从插入模式转移到命令模式。
在shell中,单词“escape”的使用稍微有所不同,它被用作引用的同义词。例如,考虑下面的例子:

echo It is warm and suny\; come over and visit

在这个例子中,我们可以说使用反斜线转义了分号。这与使用反斜线引用分号意思相同。
如果只是用来转义元字符,那么使用反斜线就够了,因为我们可以在同一行上使用不止一个反斜线。考虑下述命令:

echo It is warm (and suny); come over & visit

这条命令不能正确运行,因为这条命令有4个元字符:(、)、;和&。为了使该命令运行,需要将这4个元字符转义:

echo It is warm \(and sunny\)\; come over \& visit

在这个例子中,我们将单引号之间的所有内容引用。当然,这包括所有的字符,而不仅仅是元字符,但是它不影响字母数字式字符的显示。
因此,到目前为止,我们有两种引用元字符的方法:使用反斜线引用单个字符,或者使用单引号引用一串字符。当需要是,可以在同一条命令综合使用这两种类型的引用:

echo It is warm ‘(and sunny);’ come over \& visit

大多数时候,反斜线和单引号引用已足够。但是,在有些情形中,使用第三种类型的引用即双引号引用更加方便。下面按举例说明。
有时候,可能希望在一个引用字符串使用$字符,用来引用变量的值。例如,下述命令在尖括号中显示用户标识和终端类型:

echo My userid is <$USER>; my terminal is <$TERM>

这种形式的命令不能正常工作,因为元字符<、;和>拥有特殊的含义($字符没有什么问题。我们希望它是元字符)。解决方法就是只引用哪些我们希望取字面含义的元字符:

echo My userid is \<$USER>\; my terminal is \<$TERM>

这条命令可行,但是它非常复杂。当然,我们可以使用单引号来取代反斜线:

echo My userid is <$USER>; my terminal is <$TERM> ’

这样比较容易阅读,但是它引用了所有的元字符,包括$。这意味着只能看到字面上的$USER和$TERM,而不能看到这两个变量的值。对于这类情况,可以使用双引号,因为这样所有的$元字符将保留它们特殊的含义。例如:

echo My userid is <$USER>; my terminal is <$TERM> ”

因为我们使用双引号,所以<、;和>字符都被引用,但是$字符没有被引用(自己试试看)。‘(反引号),它拥有特殊的含义在双引号中保留,但是不再单引号中保留。

下面小节:
使用反斜线引用单个字符(成为转义了这个字符)。
使用单引号引用一串字符
使用双引号引用一串字符,但是保留$(美元)、‘(反引号)和\(反斜线)的特殊含义。

3. Linux Shell强引用和弱引用
从前面的讨论中可以看出,单引号比双引号的功能更强大。基于这一原因,有时称单引号为强引用(strong quote),双引号为弱引用(weak quote)。下面记住它们的一种简单方法:因为单引号强,所以只需要一个符号;因为双引号弱,所以需要两个符号。
实际上,反斜线是所有引用中最强的一个(尽管我们没有给他一个特殊的名称)。反斜线可以引用任何东西,因此,如果单引号不起作用,可以试一试反斜线。例如,有一天您可能转义一个单引号:

echo Don\’t let gravity get you down

反斜线功能如此强大,所以它甚至可以引用新行字符。
假设在某行的末尾键入\<Return>,这样将生成\字符后面跟新行字符。光标移动到下一行,但是由于新行字符失去它特殊的含义,所以它并不是一行结束的信号。这意味着不管接下来键入什么字符都是上一行的继续。
试试下面的例子,在每行的末尾按<Return>键:

echo This is a very, very long \
line that goes on and on for a \
very, very long time.

如果您这样做,将键入一条特别长的命令,而且将看到一行特别长的输出。
与反斜线不同,单引号和双引号不引用新行字符。情况就是这样的,您认为当在被单引号或者双引号引用的字符串中按下<Return>键时应该发生什么情况呢?例如,假设键入了下述内容:

echo ‘This line ends without a second quote

当在这一行的末尾按<Return>键时,新行字符没有被引用,因此它还保留它的特殊含义,也就是说它还标识一行的结束。但是这里有个问题因为单引号没有匹配。
如果使用的是 C-shell或者Tcsh,这时将得到一个错误信息,说明出现了一个未匹配的‘字符。
如果使用的是Bash或者Korn shell,那么shell处于等待状态,等待更久的键入,并且希望用户最终会键入第二个引号(Bourne shell比C-shell要乐观一些)。一旦键入了第二个引号,shell就会将所有的内容组合成一个非常长的命令,命令中间含有新行字符。
作为练习,键入下述两行内容,看看shell如何处理:

echo ‘This line ends without a matching quote
and here is the missing quote’




沒有留言:

張貼留言