我在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
答案 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。