Bash的优雅简洁似乎在庞大的手册页中迷失了。
除了上述出色的解决方案之外,我还想为您提供有关bash如何解析和解释语句的速查表。然后,使用此路线图,我将分析发问者提出的示例,以帮助您更好地理解它们为什么无法按预期运行。
注意:Shell脚本行直接使用。输入的输入行首先进行历史扩展。
每个bash行首先被标记化,或者换句话说,被切成所谓的标记。(令牌化发生在所有其他扩展之前,包括大括号,代字号,参数,命令,算术,过程,单词拆分和文件名扩展。)
此处的令牌表示输入行的一部分由以下特殊元字符之一分隔(定界):
space, - White space...
tab,
newline,
‘<’, - Redirection & piping...
‘|’,
‘>’
‘&’, - And/Both < | > | >> .or. &<file descriptor>
‘;’, - Command termination
‘(’, - Subshell, closed by - ‘)’
Bash使用许多其他特殊字符,但是只有这10个特殊字符会产生初始标记。
但是,由于有时有时必须在令牌中使用这些元字符,因此需要一种方法来消除其特殊含义。这称为转义。逸出的,(即,通过引用的一个或多个字符的字符串要么完成'xx..'
,"xx.."
),或者通过用反斜线,(即前缀个别字符\x
)。(它比这复杂一点,因为引号也需要加引号,并且双引号不能引出所有内容,但是这种简化现在才有用。)
不要将bash引用与引用文本字符串的思想混淆,就像其他语言一样。bash中引号之间的内容不是字符串,而是输入行中转义了元字符的部分,因此它们不分隔标记。
请注意,'
和和之间有一个重要区别"
,但这是另一天的区别。
其余未转义的元字符将成为令牌分隔符。
例如,
$ echo "x"'y'\g
xyg
$ echo "<"'|'\>
<|>
$ echo x\; echo y
x; echo y
在第一个示例中,由空格分隔符产生了两个标记:echo
和xyz
。
同样在第二个示例中。
在第三个例子中,分号被转义,所以有一个空格分隔符,产生4个令牌echo
,x;
,echo
,和y
。然后,第一个令牌将作为命令运行,并将接下来的三个令牌作为输入。注意第二个echo
没有执行。
要记住的重要一点是,庆典首先查找转义字符('
,"
,和\
),然后查找转义元字符分隔符,按照这个顺序。
如果不进行转义,则这10个特殊字符将用作token
分隔符。其中一些还具有其他含义,但首先,它们是标记定界符。
grep期望什么
另外,在上述的grep的例子中需要这些令牌,grep
,string
,filename
。
这个问题的第一次尝试是:
$ grep(then | there)xx
在这种情况下(
,)
和|
是未转义元字符等用于将输入划分成这些令牌:grep
,(
,then
,|
,there
,)
,和x.x
。grep的希望看到grep
,then|there
和x.x
。
问题的第二尝试是:
grep“(then | there)” xx
这将标记化grep
,(then|there)
,x.x
。如果将grep换成echo,则可以看到以下内容:
回显“(然后|那里)” xx
(然后|那里)xx