Bash 如何在';如果';条件

Bash 如何在';如果';条件,bash,unix,Bash,Unix,我正在创建一个bash脚本,其中包含以下代码: if [ $# -eq 2 -a (! -r "$2" -o ! -f "$2") ]; then echo "rvf: bestand \""$2"\" bestaat niet of is onleesbaar" 1>&2 exit 2 fi 当我尝试在脚本中运行此命令时,会出现以下错误: Syntax Error (bash -n): rvf: line 14: syntax error in conditional expr

我正在创建一个bash脚本,其中包含以下代码:

if [ $# -eq 2 -a (! -r "$2" -o ! -f "$2") ]; then
echo "rvf: bestand \""$2"\" bestaat niet of is onleesbaar" 1>&2
exit 2
fi
当我尝试在脚本中运行此命令时,会出现以下错误:

Syntax Error (bash -n):
rvf: line 14: syntax error in conditional expression
rvf: line 14: syntax error near `-a'
rvf: line 14: `if [[ $# -eq 2 -a (! -r "$2" -o ! -f "$2") ]]; then'

“()”在Bash脚本中是如何工作的?

这里有多个混淆点

  • [
    可以(作为标准的可选XSI扩展)支持
    作为一个单独的词(意思是它周围需要有空格),但将它(如
    -a
    -o
    )标记为“过时”,并建议不要使用它
  • [[
    确实支持
    ),但它必须始终是一个单独的单词
不过,不要这样做。如果每个测试都有自己的简单命令,并且仅将它们与shell的布尔逻辑支持相结合,那么您只能使用支持良好的可移植功能

即:

if [ "$#" -eq 2 ] && { [ ! -r "$2" ] || [ ! -f "$2" ]; }; then
  echo "rvf: bestand \"$2\" bestaat niet of is onleesbaar" >&2
  exit 2
fi

[
不支持
-a
,对于
[
,它被认为是过时的且不可移植的。使用
[
的正确解决方案是

if [ "$#" -eq 2 ] && { [ ! -r "$2" ] || [ ! -f "$2" ]; }; then
分组是使用
{…}
而不是
(…)
完成的,以避免创建不必要的子shell

使用
[[
可以简化为

if [[ "$#" -eq 2 && ( ! -r "$2" || ! -f "$2" ) ]]; then
括号可用于在
[[
内部进行分组;作为一个复合命令,它使用单独的解析和求值规则,而不是像
[
这样的普通命令(它只是
测试的别名,而不是任何语法)

在这两种情况下,您都可以将其重构为更简单的内容:

if [ "$#" -eq 2 ] && ! { [ -r "$2" ] && [ -f "$2" ] }; then

if [[ "$#" -eq 2 && ! ( -r "$2" && -f "$2" ) ]]; then

重新构建您的逻辑。
“不是A或不是B”只是说“不是(A和B)”的更复杂的方式

bash
中,尝试

if [[ "$#" == 2 ]] && ! [[ -r "$2" && -f "$2" ]]; then
更好

if [[ "$#" == 2 && -r "$2" && -f "$2" ]]
then : all good code
else : nope code
fi
更好的是

if [[ "$#" == 2 ]]            # correct args
then if [[ -r "$2" ]]         # is readable
     then if [[ if -f "$2" ]] # is a file
          then echo "all good"
               : do all good stuff
          else echo "'$2' not a file"
               : do not a file stuff
          fi
     else echo "'$2' not readable"
          : do not readable stuff
     fi
else echo "Invalid number of args"
     : do wrong args stuff
fi
清除错误日志是值得分清的

更好,伊姆霍-


您是否在错误消息中使用了
[
类似您发布的代码或
[
类似的代码?顺便说一句,请注意
[
[
都不是“
if
语法”;它们是独立的命令,如果涉及
,则可以不使用
(和
if
可以在不使用其中任何一个的情况下使用;
if somecommand;然后…
将检查
somecommand
是否返回零或非零退出状态,无论该命令是什么)。另一方面,
$2
应该用引号引起来,以防止其值被分词和全局扩展——因此您应该只使用
echo“…$2…”
而不是
echo“…$2…”
;如果要防止任何直接连接在右侧的字符被解析为尝试的变量名的一部分,则
应回送“..${2}…”
。(引用
$#
还可以防止在使用
[
而不是
时出现包含数字字符的疯狂IFS值问题[[
,所以这无论如何都不是一个坏习惯。)是的;我将删除注释并暗示这是必要的:)
if [[ "$#" != 2 ]]
then : wrong args stuff
fi
if [[ ! -r "$2" ]]
then : unreadable stuff
fi
if [[ ! -f "$2" ]] 
then : do not a file stuff
fi

: do all good stuff