指定 -a 和 -o 二进制原色以及“(”和“)”运算符的 XSI 扩展已被标记为过时。 (许多使用它们的表达式是由语法模糊定义的,具体取决于正在评估的特定表达式。)使用这些表达式的脚本应转换为下面给出的形式。尽管许多实现将继续支持这些过时的形式,但脚本在处理用户提供的输入时应该非常小心,因为这些输入可能会与这些和其他原色和运算符混淆。除非应用程序开发人员知道向脚本生成输入的所有情况,否则调用如下:
test "$1" -a "$2"
应写为:
test "$1" && test "$2"
“‘(’和‘)’运算符已被标记为过时”。
(
和 是)
对命令进行分组并创建子 shell 的运算符吗?如果它们已经过时,那么它们的替代品是什么?
应该
test "$1" -a "$2"
替换为test "$1" && test "$2"
,还是替换为(( test "$1" && test "$2" ))
?我们不需要像原始命令
((...))
一样返回 0 或 1吗?test
答案1
(
和 是)
对命令进行分组并创建子 shell 的运算符吗?
不,该文档引用了使用以下方式对表达式进行分组的运算符test
:
test 0 -eq 0 -a \( 0 -eq 1 -o 1 -eq 1 \)
如果它们已经过时,那么它们的替代品是什么?
它们的替代品是()
和{}
,类似地,它们在 shell 级别对命令进行分组:
test 0 -eq 0 && (test -0 -eq 1 || test 1 -eq 1)
test 0 -eq 0 && { test -0 -eq 1 || test 1 -eq 1; }
很容易看出这种模式:test
for 表达式中使用的每个运算符都被替换为 shell 中等效的 for 命令。
应该
test "$1" -a "$2"
替换为test "$1" && test "$2"
,还是替换为(( test "$1" && test "$2" ))
?
应将其替换为test "$1" && test "$2"
;(())
用于算术扩展,与命令的退出状态无关,因为其目的是计算算术表达式。例如,这将是有效的:
(( $(test 1 -eq 1 && echo $?) && $(test 0 -eq 0 && echo $?) ))
(注意命令替换,它被替换为内部命令的退出状态,0
并且0
;计算的表达式实际上是(( 0 && 0 ))
)。
但这会导致语法错误:
(( test 1 -eq 1 && test 0 -eq 0 ))
$ (( test 1 -eq 1 && test 0 -eq 0 ))
bash: ((: test 1 -eq 1 && test 0 -eq 0 : syntax error in expression (error token is "1 -eq 1 && test 0 -eq 0 ")
答案2
用更简单的语言强调一个非常重要的事实:
您在屏幕上键入的字符可能会或可能不会被您调用的命令“看到”(接收)。您可能对此很熟悉;每次你引用某些东西时都会发生这种情况。
这壳看到您输入的每个字符。 shell 对于如何处理这些字符有自己的规则。例如,该echo
命令在以下每个实例中“看到”完全相同的内容:
$ echo hello
hello
$ echo "hello"
hello
$ echo 'hello'
hello
$ echo \h\e\l\l\o
hello
$ echo 'h'"e"\l$'lo'
hello
$ somevar=hello;echo $somevar
hello
$ somevar='h'"el"\l\o;echo $somevar
hello
$
就像命令永远不会“看到”上面的引号和反斜杠一样echo
,shell 会专门处理括号。所以,当未引用时,除了外壳之外,其他任何东西都看不到它们。
一个很好的例子是命令find
,它接受括号作为论点。对于括号抵达命令find
并且不会由 shell 进行特殊解释,因此必须将它们加引号或转义以删除其对 shell 的特殊含义。请注意,引号和转义符确实不是到达find
命令;只有括号可以:
(从另一个问题在这个网站上:)
# What you type:
find ~ \( -type f '-ex'ec ch\mod 600 {} + ')' -o \
"(" -type d -exec c"hmo"d 700 {} ';' \)
# What the find command sees:
/home/tim ( -type f -exec chmod 600 {} + ) -o ( -type d -exec chmod 700 {} ; )
# If you typed this...
find ~ \( -type f -exec chmod 600 {} + ) -o \
\( -type d -exec chmod 700 {} + \)
# ...find doesn't see anything, because bash runs into an error condition
# before it can even parse the line. That close paren is special to bash.
还有一个与此相关的俚语。当您打算让命令“看到”特殊字符(通常是单引号或双引号,但也可以包含反斜杠或空格字符)并且由于引用和转义中的错误,该命令永远看不到该字符时,我们说 shell“吃掉”了引用。
一个有趣的吃引用的例子(以及围绕它的困难)包括:编写一个 ssh 命令,该命令将登录到远程服务器,启动 bash 会话,并运行命令sed
来修改存储在文件,以便正确引用它以包含在 HTTP 消息中。
话虽如此,这是一个简短的答案:
- “‘(’和‘)’运算符已被标记为过时”。
( 和 ) 是对命令进行分组并创建子 shell 的运算符吗?
如果它们已经过时,那么它们的替代品是什么?
括号对于 shell 仍然具有特殊含义,并且并未过时。过时的是将括号传递给test
命令(通过引用它们以防止 shell 吃掉它们)。
*这显然取决于您对“乐趣”的定义。