Bash `test`在当前shell中查找脚本时,比较的行为不同

Bash `test`在当前shell中查找脚本时,比较的行为不同,bash,shell,Bash,Shell,我在bash脚本中有一个令人惊讶的行为。脚本如下所示,我已尽可能简化: test.sh: DBOK=$(sqlplus -s user/xxx as sysdba<<EOF set feed off pages 0 echo off SELECT decode(value,'TRUE','CLUSTER','FALSE','NONCLUSTER','UNKNOWN') from v\$parameter where name='cluster_database'; EOF ) ech

我在bash脚本中有一个令人惊讶的行为。脚本如下所示,我已尽可能简化:

test.sh:

DBOK=$(sqlplus -s user/xxx as sysdba<<EOF
set feed off pages 0 echo off
SELECT decode(value,'TRUE','CLUSTER','FALSE','NONCLUSTER','UNKNOWN') from v\$parameter where name='cluster_database';
EOF
)
echo x"$DBOK"y
set -x
if [ "${DBOK}" == NONCLUSTER ]; then
echo "not a cluster do nothing"
fi
set +x
但是,如果我在“点空间斜杠”模式下运行脚本(根据需要:最终目标是修改当前进程的env),它将不起作用:

. /path/test.sh

test

    xNONCLUSTERy
    ++ '[' 'NONCLUSTER' == NONCLUSTER ']'
    ++ set +x
作为sql脚本的结果加载变量可以很好地工作,并且结果看起来很好。但是在进行测试比较时,在当前进程中运行脚本似乎会破坏它

任何帮助都将不胜感激,我已经干涸了

在Adrian的评论之后使用hextump命令进行编辑:

$./test.sh

00000000  4e 4f 4e 43 4c 55 53 54  45 52 0a |NONCLUSTER.| 
0000000b 
xNONCLUSTERy
++ [[ NONCLUSTER == NONCLUSTER ]]
++ echo 'not a cluster do nothing' not a cluster do nothing
++ set +x
00000000  1b 5d 30 3b 6f 72 61 63  6c 65 40 6e 61 74 71 6f  |.]0;oracle@natqo|
00000010  72 61 30 34 3a 7e 2f 73  63 72 69 70 74 73 2f 74  |ra04:~/scripts/t|
00000020  6f 6f 6c 73 20 7c 20 73  71 6c 70 6c 75 73 20 2d  |ools | sqlplus -|
00000030  73 20 6c 65 64 62 61 40  51 42 4f 41 55 44 49 54  |s ledba@QBOAUDIT|
00000040  20 61 73 20 73 79 73 64  62 61 07 4e 4f 4e 43 4c  | as sysdba.NONCL|
00000050  55 53 54 45 52 0a                                 |USTER.|
00000056
xNONCLUSTERy
++ [[ NONCLUSTER == NONCLUSTER ]]
++ set +x
美元/test.sh

00000000  4e 4f 4e 43 4c 55 53 54  45 52 0a |NONCLUSTER.| 
0000000b 
xNONCLUSTERy
++ [[ NONCLUSTER == NONCLUSTER ]]
++ echo 'not a cluster do nothing' not a cluster do nothing
++ set +x
00000000  1b 5d 30 3b 6f 72 61 63  6c 65 40 6e 61 74 71 6f  |.]0;oracle@natqo|
00000010  72 61 30 34 3a 7e 2f 73  63 72 69 70 74 73 2f 74  |ra04:~/scripts/t|
00000020  6f 6f 6c 73 20 7c 20 73  71 6c 70 6c 75 73 20 2d  |ools | sqlplus -|
00000030  73 20 6c 65 64 62 61 40  51 42 4f 41 55 44 49 54  |s ledba@QBOAUDIT|
00000040  20 61 73 20 73 79 73 64  62 61 07 4e 4f 4e 43 4c  | as sysdba.NONCL|
00000050  55 53 54 45 52 0a                                 |USTER.|
00000056
xNONCLUSTERy
++ [[ NONCLUSTER == NONCLUSTER ]]
++ set +x

获取脚本时,您正在运行哪个shell

由于输出看起来不一样(
NOCLUSTER
vs.
'NOCLUSTER'
),我假设它不是同一个shell,并且您当前运行的shell可能不允许将
=
与不可移植的单括号表示法结合使用(但大多数现代shell允许)

对于支持它的shell,应该使用
[…=…]
[…==…]]
。我通常使用单括号表示法,除非我特别需要一个只随
[[
一起提供的功能,比如
=~
操作符

我似乎无法重现这一点:

$ /bin/bash --noprofile --norc


但对此类行为没有解释,但解决方法是分两步加载变量:

sqlplus -s ledba/xxx as sysdba<<EOF
spool /tmp/test.lst
set feed off pages 0 echo off
SELECT decode(value,'TRUE','CLUSTER','FALSE','NONCLUSTER','INCONNU') from v\$parameter where name='cluster_database';
spool off
EOF
DBOK=`cat /tmp/test.lst|sed 's/ *$//'`
sqlplus-s ledba/xxx作为sysdba我怀疑您的默认shell不是您认为的
bash
。您使用的bash语法是
=
,而正常的非bash测试无法识别
=
。有两种选择:

  • 使用
    =
    作为测试,而不是
    =
    。这将适用于所有基于Posix的Shell和原始Bourne Shell
  • #!/bin/bash
    添加到脚本顶部,以保证您使用的是bash而不是其他shell。永远不要使用shell。如果您完全使用bash,请在测试中使用
    […]
    而不是
    […]
    。这在Kornshell、Dash和Ash shell中也适用
即使
/bin/sh
链接到
/bin/bash
,当通过
sh
调用bash时,bash的行为也不像bash。相反,它据称是在纯POSIX模式下运行的(我之所以这么说,是因为Kornshell是一个完全兼容POSIX的shell,我知道Kornshell所做的某些事情在
/bin/sh
中无法工作)


在Mac OS X上,
/bin/sh
链接到
/bin/bash
。在Linux系统上,他们使用Ash或Dash shell作为
/bin/sh
,这应该更符合POSIX。

感谢您的输入,Adrian。不幸的是,它没有解决这个问题。shell是/bin/bash,我测试了单/双的所有组合括号中有=或==,但我得到了相同的结果。但是我现在有[[NONCLUSTER==NONCLUSTER]]处于“点空间斜线模式”?我更新了我的帖子,我无法重现你看到的行为。再次感谢Adrian。我得到了与你相同的反馈(除了我的“sh t.sh”没有错误,而是我的“sh”命令链接到bash,因此它在逻辑上工作)如您所见,我用x和y括起来检查变量是否有多余字符,但我必须假设有多余字符,这是sql oracle查询的结果?这个小错误是一个真正的噩梦,我看不到任何解决方法或替代方法来测试…!Atb。我的
sh
也是
bash
,但这并不能解释它为什么工作。如果作为
sh
bash
调用,将进入
POSIX
-兼容模式,因此实际上它不应该工作,除非此行为发生改变,但我在
bash
更改日志中找不到任何支持此假设的内容。您使用的是
bash
的哪个版本?我同意,但我测试了非printa的阅读我生成的一个文件中的ble字符以及
set-x
的输出清楚地显示了该变量包含特殊字符(不管怎样,我的shell)所以我也不这么认为。但是你还是应该通过做一些检查,例如,
hextump-C Bingo-Adrian,你太棒了!我回来时给出了完整的解释,但基本上我的变量不包含它在“点空间斜杠”中似乎包含的内容模式。#!/bin/bash解决了问题。我不应该信任$SHELL或任何其他测试。多亏了Adrian和David!这不正是我说的吗?还有,“在Linux系统上”这是一个错误的概括,不是每个Linux发行版都默认为
/bin/sh
ash
dash
bash-4.2$ . ./t.sh
++ '[' NONCLUSTER = NONCLUSTER ']'
++ echo true
true
++ '[' NONCLUSTER == NONCLUSTER ']'
++ echo true
true
++ [[ NONCLUSTER == NONCLUSTER ]]
++ echo true
true
bash-4.2$ sh t.sh
+ sh t.sh
+ [ NONCLUSTER = NONCLUSTER ]
+ echo true
true
+ [ NONCLUSTER == NONCLUSTER ]
t.sh: 6: [: NONCLUSTER: unexpected operator
+ echo false
false
+ [[ NONCLUSTER == NONCLUSTER ]]
t.sh: 7: t.sh: [[: not found
+ echo false
false
sqlplus -s ledba/xxx as sysdba<<EOF
spool /tmp/test.lst
set feed off pages 0 echo off
SELECT decode(value,'TRUE','CLUSTER','FALSE','NONCLUSTER','INCONNU') from v\$parameter where name='cluster_database';
spool off
EOF
DBOK=`cat /tmp/test.lst|sed 's/ *$//'`