linux报错:unexpected EOF while looking for matching `"

调试

    编写完一个脚本之后,就要第一次运行它了。但是,如果在执行脚本时显示某些意外的错误,应该怎么办呢?没有人是完美的,而且从头编写脚本并保持没有错误需要大量时间和丰富的经验;大多数时候,开发人员很容易漏掉一个字母或者颠倒了两个字母的顺序,这几乎是不可避免的。不必担心:AIX、其他风格的 UNIX 和 Linux 中的 shell 已经考虑到了这个问题,可以帮助您进行调试。

    例如,清单 10 中的 shell 脚本(名为 make_errors)已经编写好等待执行。

    清单 10. 包含错误的脚本示例

   


 #!/bin/bash

_X=1

while [[ ${_X} -le 10 ]]

do

  [[ ${_X} -lt 5 ]] && echo "X is less than 5!

  _Y=`expr ${_X) + 1`

  if [[ ${_Y} -eq 6 ]]

    echo "Y is now equal to ${_Y}"

  fi

  _X=${_Y}

done


    但是,初次执行这个脚本时,显示以下错误:

  


 

# ./make_errors./make_errors: line 11: unexpected EOF while looking for matching `"'./make_errors: line 16: syntax error: unexpected end of file


    Vim 是一种出色的调试工具,您可能使用过它,但不一定了解它的真正价值。Vim 是一种强大的文本编辑器,但是它对调试也很有帮助。如果通过设置 .exrc 或 .vimrc 文件指定用不同的颜色显示某些错误,Vim 就会替您完成大部分调试工作,见图 1。

    图 1. 用 Vim 进行调试

   

    第一个错误消息(line 11: unexpected EOF while looking for matching `"')指出在第 11 行上有错误,但是看过这一行之后,并没有发现任何错误。再看看第 9 行。echo 后面的字符串的末尾缺少一个双引号(")。这个示例很好地说明了在进行调试时为什么必须查看整个脚本。错误消息中显示的行号不一定是出现错误的实际位置。报告第 11 行有错误是因为第 9 行用双引号标出一个字符串的开头,但是这个字符串直到第 11 行还没有结束。要想纠正这个错误,应该在第 9 行末尾添加双引号。

    其他一些问题也会显示为错误。在第 11 行上,变量值 _X 后面是一个用红色突出显示的后圆括号())。这是 Vim 替您做出的判断,它指出这里有错误。这里用一个前花括号({)标出了变量值 _X 的开头,但是没有用后花括号(})结束。只需把 ) 改为 },就能够纠正这个错误。

    到目前为止,已经纠正了两个错误。再次运行这个脚本,看看会发生什么:

   


 

./make_errors: line 12: syntax error near unexpected token `fi'./make_errors: line 12: ` fi'


    还有另一个错误。错误消息指出问题出现在第 12 行上,但是这一行只有一个用来结束 if 语句的 fi。这有什么错呢?请牢记前一个错误的情况。并非所有错误都源自 shell 所报告的行上。shell 仅仅报告发生错误的位置,但是错误的根源可能出现在这个位置之前。对于这个小脚本,可以很有把握地猜测错误可能出现在实际的 if 语句中。回忆一下基本的脚本编程逻辑:if 语句由 if、then 和 fi 组成。看看这个条件语句,可以看出缺少了 then。只需在脚本中添加 then。完成之后,这个脚本应该类似于清单 11。

    清单 11. 纠正清单 10 中的错误之后的脚本

   


 #!/bin/bash

_X=1

while [[ ${_X} -le 10 ]]

do

  [[ ${_X} -lt 5 ]] && echo "X is less than 5!"

  _Y=`expr ${_X} + 1`

  if [[ ${_Y} -eq 6 ]]

  then

    echo "Y is now equal to ${_Y}"

  fi

  _X=${_Y}

done


    再次运行这个脚本:

   


 

# ./make_errorsX is less than 5!X is less than 5!X is less than 5!X is less than 5!Y is now equal to 6


    恭喜!这个脚本现在正常工作了!

    set -x 选项

    有时候,对 shell 脚本执行基本的错误排除步骤并不像前一个示例那么容易。如果所有努力都失败了,并且想不出脚本的错误之处在哪里,那么最后一招就是动用 “杀手锏”!Ksh、Bash 和其他现代 shell 都支持在 set 命令中使用 -x 开关。如果使用 set –x 选项,执行的每个命令都显示在 stdout 中。为了突出显示执行的代码,set –x 把 PS4 变量的值加在显示的每行代码前面。请记住,这种做法会产生大量文本,所以在查看输出时要有耐心。

    减小前一个示例中的循环计数值,在脚本的开头添加 set -x 和一个注释,见清单 12。

    清单 12. set -x 示例

   


 #!/bin/bash

set -x

# loop through and display some test statements

_X=1

while [[ ${_X} -le 4 ]]

do

  [[ ${_X} -lt 2 ]] && echo "X is less than 2!

  _Y=`expr ${_X} + 1`

  if [[ ${_Y} -eq 3 ]]

  then

    echo "Y is now equal to ${_Y}"

  fi

  _X=${_Y}

done


    在执行这个脚本之前,把 PS4 变量改为某个看起来醒目的字符串:

  


 

# export PS4="DEBUG => "


    接下来,执行这个脚本,就会看到可能非常有价值的信息,见清单 13。

    清单 13. set -x 的输出

   


 

# ./make_errorsDEBUG => _X=1DEBUG => [[ 1 -le 4 ]]DEBUG => [[ 1 -lt 2 ]]DEBUG => echo 'X is less than 2!'X is less than 2!DDEBUG => expr 1 + 1DEBUG => _Y=2DEBUG => [[ 2 -eq 3 ]]DEBUG => _X=2DEBUG => [[ 2 -le 4 ]]DEBUG => [[ 2 -lt 2 ]]DDEBUG => expr 2 + 1DEBUG => _Y=3DEBUG => [[ 3 -eq 3 ]]DEBUG => echo 'Y is now equal to 3'Y is now equal to 3DEBUG => _X=3DEBUG => [[ 3 -le 4 ]]DEBUG => [[ 3 -lt 2 ]]DDEBUG => expr 3 + 1DEBUG => _Y=4DEBUG => [[ 4 -eq 3 ]]DEBUG => _X=4DEBUG => [[ 4 -le 4 ]]DEBUG => [[ 4 -lt 2 ]]DDEBUG => expr 4 + 1DEBUG => _Y=5DEBUG => [[ 5 -eq 3 ]]DEBUG => _X=5DEBUG => [[ 5 -le 4 ]]


    可以看到这里有大量信息:处理并执行的每个命令都显示出来了。还要注意,在调试信息中没有显示 shell 脚本中的注释。这是因为 shell 在读取注释之后并不执行它。还好,在完成前面的修改之后,这个脚本没有错误了!

    在使用 set -x 时还要记住一点:如果脚本有内部函数,而且 set -x 放在代码的主体部分,那么它的输出会包含子函数的运算过程。但是,如果 set -x 只放在内部函数中,那么 debug 选项的影响范围只包含这个内部函数中的代码和在其中调用的子函数;shell 脚本的主体并不包含在内,这是因为它不知道它的内部函数会调用这个例程。

   结束语

   无论是使用 shell 脚本、C、Java? 语言或其他语言,我们都在不断地改进编程方法。坚持简单化的基本规则,保持代码简洁灵活,给代码加上适当的注释,再借助调试工具的帮助,您很快就能编写出出色的 shell 脚本。祝您好运!

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/29119536/viewspace-1132305/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/29119536/viewspace-1132305/

你可能感兴趣的:(linux报错:unexpected EOF while looking for matching `")