在当前shell中获取脚本时,`test`比较的行为有所不同

时间:2014-03-26 09:51:07

标签: 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
)
echo x"$DBOK"y
set -x
if [ "${DBOK}" == NONCLUSTER ]; then
echo "not a cluster do nothing"
fi
set +x

如果我直接执行此脚本,它可以正常工作:

bash ./path/test.sh

    > xNONCLUSTERy
    > ++ '[' NONCLUSTER == NONCLUSTER ']'
    > ++ echo 'not a cluster do nothing'
    > ++ set +x

但是,如果我在&#34;点空间斜线中运行脚本&#34;模式(根据需要:最终目标是修改当前流程的环境),它不起作用:

. /path/test.sh

test

    xNONCLUSTERy
    ++ '[' 'NONCLUSTER' == NONCLUSTER ']'
    ++ set +x

由于sql脚本的加载变量工作正常,结果似乎很好。但是当进行测试比较时,看起来在当前进程中运行脚本会破坏它???

任何帮助都会受到赞赏,我干了!

根据Adrian的评论使用hexdump命令进行编辑:

$ ./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

$。 ./test.sh

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

3 个答案:

答案 0 :(得分:0)

在采购脚本时您正在运行哪个shell?

由于输出看起来不一样(NOCLUSTER'NOCLUSTER'),我认为它不是同一个shell,并且您当前运行的shell可能无法容忍==与单支架符号结合使用,不便携(但大多数现代外壳都允许)。

对于支持它的shell,您应该使用[ ... = ... ] [[ ... == ... ]]。我通常坚持使用单括号表示法,除非我特别需要一个只有[[运算符=~附带的功能。

我似乎无法重现这一点:

$ /bin/bash --noprofile --norc

bash-4.2$ cat t.sh
#!/bin/bash

foo=NONCLUSTER
set -x
[ "${foo}" = NONCLUSTER ]    && echo true || echo false
[ "${foo}" == NONCLUSTER ]   && echo true || echo false
[[ "${foo}" == NONCLUSTER ]] && echo true || echo false

bash-4.2$ ./t.sh
+ '[' NONCLUSTER = NONCLUSTER ']'
+ echo true
true
+ '[' NONCLUSTER == NONCLUSTER ']'
+ echo true
true
+ [[ NONCLUSTER == NONCLUSTER ]]
+ echo true
true

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

答案 1 :(得分:0)

然而,没有解释这种行为,但解决方法是分两步加载变量:

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/ *$//'`

然后比较可以顺利进行......

无论如何,多亏了阿德里安的宝贵时间!

答案 2 :(得分:0)

我怀疑你的默认 shell不是bash。您正在使用带有==的Bash语法,而正常的非bash测试无法识别==。两个选择:

  • 使用=代替==进行测试。这适用于所有基于Posix的shell和原始的Bourne Shell。
  • #! /bin/bash添加到脚本顶部以确保您使用的是Bash而不是其他shell。永远不要假设壳。而且,如果您要使用所有Bash,请在测试中使用[[ ... ]]而不是[ ... ]。这也适用于Kornshell,Dash和Ash shell。

即使/bin/sh/bin/bash相关联,Bash在通过sh调用时也不像Bash。相反,据称它以纯POSIX模式运行。 (据说我说Kornshell是一个完全符合POSIX标准的shell,我知道Kornshell所做的某些事情在/bin/sh中不起作用。)

在Mac OS X上,/bin/sh/bin/bash相关联。在Linux系统上,他们使用/bin/sh的Ash或Dash shell,假设它更符合POSIX。