Shell 脚本 - 意外标记“else”附近的语法错误

Jac*_*cob 18 shell oracle-database shell-script

使用以下 shell 脚本,为什么会出现错误

syntax error near unexpected token `else'
Run Code Online (Sandbox Code Playgroud)

外壳脚本

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
Run Code Online (Sandbox Code Playgroud)

les*_*ana 32

你必须终止这样的条件if

if [ "${ORACLE_SID}" != 'Test' ]; then
                                ^ semicolon
Run Code Online (Sandbox Code Playgroud)

或者像这样:

if [ "${ORACLE_SID}" != 'Test' ]
then
                                ^ newline
Run Code Online (Sandbox Code Playgroud)

注意:您还必须在 之后[和之前放置空格]

;or换行的原因是if语句的条件部分只是一个命令。任何长度的任何命令,准确地说。shell 执行那个命令,检查命令的退出状态,然后决定是执行then部分还是else部分。

因为命令可以是任意长度,所以需要一个标记来标记条件部分的结束。那是;或 换行符,后跟then.

后面[有空格的原因是因为[是一个命令。通常是shell的内置。shell 执行命令[,其余部分作为参数,包括]作为强制的最后一个参数。如果你没有[在 shell后面放一个空格,它会尝试[whatever作为命令执行而失败。

之前空格的原因]是类似的。因为否则它不会被识别为它自己的参数。


Kus*_*nda 5

您可以使用在线ShellCheck(也可作为独立工具提供)轻松检查您的 shell 脚本。

在这种情况下,它会指出 if 语句需要空格, after[和 before ],并且在同一行;之前需要一个(或换行符)then

当你解决了这个问题后,它会继续告诉你它USER_NAME被使用而没有被初始化为任何东西。这是因为您还有一个user_name变量(大小写很重要)。PASS和也是如此pass

它还告诉您使用read -rto stop readfrom mangling \(例如,对于密码可能很重要),并且您应该在调用时将变量双引号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
Run Code Online (Sandbox Code Playgroud)

在这里,我还通过临时将IFS密码设置为空字符串来使用带有前导或尾随空格字符的密码read

如果$ORACLE_SID/$sid是,则逻辑也已更改为退出Test。这避免了将脚本的主要操作部分放在if分支中。