使用以下 shell 脚本,为什么我会收到错误
syntax error near unexpected token `else'
外壳脚本
echo "please enter username"
read user_name
echo "please enter password"
read -s pass
echo ${ORACLE_SID}
SID=${ORACLE_SID}
if ["${ORACLE_SID}" != 'Test'] then
sqlplus -s -l $USER_NAME/$PASS@$SID <<EOF
copy from scott/tiger@orcl insert EMP using select * from EMP
exit
EOF
else
echo "Cannot copy"
fi
答案1
您必须像这样终止条件部分(方括号):
带分号
if [ "${ORACLE_SID}" != 'Test' ]; then
^ semicolon
或换行符
if [ "${ORACLE_SID}" != 'Test' ]
^ newline
then
注意:您还必须在[
之前和之后添加空格]
。
[ "${ORACLE_SID}" != 'Test' ]
^ space ^ space
背景
或换行的原因;
是if
语句的条件部分只是一个命令。准确地说,任何长度的任何命令。 shell 执行该命令,检查该命令的退出状态,然后决定是否执行该then
部分或该else
部分。
由于命令可以是任意长度,因此需要有一个标记来标记条件部分的结尾。即;
或 换行符,后跟then
。
后面有空格的原因[
是因为它[
是一个命令。通常是 shell 的内置组件。 shell 执行命令时[
将其余部分作为参数,包括]
最后一个强制参数。如果在 shell 后面不加空格,[
它将尝试[whatever
作为命令执行并失败。
前面的空格的原因]
是类似的。因为否则它不会被识别为它自己的参数。
答案2
您可以使用以下命令轻松检查您的 shell 脚本外壳检查在线(也可作为独立工具使用)。
在这种情况下,它会指出 if 语句需要空格,after[
和 before ,并且在同一行的之前]
需要一个;
(或换行符) 。then
当你解决这个问题后,它会继续告诉你它USER_NAME
被使用而没有被初始化为任何东西。这是因为您还有一个user_name
变量(大小写很重要)。对于PASS
和 也是如此pass
。
它还告诉您使用read -r
来阻止read
损坏\
(例如,这对于密码可能很重要),并且您应该在调用时对变量加双引号,sqlplus
以防止 shell 意外地进行文件名匹配和分词(这同样很重要,如果例如,密码包含文件通配字符(如*
、 或空格)。
缩进代码也将使其更具可读性:
#!/bin/bash
read -r -p 'please enter username: ' user_name
IFS= read -rs -p 'please enter password: ' pass
printf 'ORACLE_SID = %s\n' "$ORACLE_SID"
sid=$ORACLE_SID
if [ "$sid" = 'Test' ]; then
echo 'Cannot copy' >&2
exit 1
fi
sqlplus -s -l "$user_name/$pass@$sid" <<'SQL_END'
copy from scott/tiger@orcl insert EMP using select * from EMP
exit
SQL_END
IFS
在这里,我还通过临时设置为空字符串来读取密码,从而可以使用带有前导或尾随空格字符的密码read
。
逻辑也被更改为如果$ORACLE_SID
/$sid
是 则退出Test
。这避免了脚本的主要操作部分位于if
分支中。
答案3
写作时sh
你想要
if [ "$ORACLE_SID" != "Test" ]
then
...
fi
写作时bash
if [[ "$ORACLE_SID" != "Test" ]]
then
...
fi
请注意空格。和第一个运算符之间必须有一个空格[[
。