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

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

使用以下 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

请注意空格。和第一个运算符之间必须有一个空格[[

相关内容