在不运行的情况下检查BASH脚本的语法
1. 概述
在本教程中,我们将学习如何在不运行 Bash 脚本的情况下验证其语法。我们将仔细研究可用于此目的的一些 Bash 和第三方实用程序。
2. 设置
首先,让我们编写一个帮助程序脚本,我们将在本教程的大部分内容中使用它:
$ cat unity_check.sh
#! /bin/bash
read -p "Enter the input: " num1
if [ -z "$num1" ]
then
echo "The number is empty"
exit 0
fi
if [ "${num1}" -eq 1 ]
then
echo "Number entered is 1"
else
echo "Not equal to One !!"
fi
此脚本测试用户输入的数字是否等于 1。
现在,让我们深入讨论并学习在语法上验证它的方法。
3.使用noexec模式进行语法检查
在某些情况下,我们可能希望在执行脚本之前对其进行语法验证。如果是这样**,我们可以使用*-n选项调用noexec*模式**。结果,Bash 将读取命令但不执行它们。
让我们以noexec模式执行我们的unity_check.sh脚本:
$ bash -n ./unity_check.sh
$
由于没有语法错误,这会产生空白输出。现在,我们将稍微修改脚本并从第二个if条件中删除then语句:
$ cat unity_check_error.sh
#! /bin/bash
read -p "Enter the input: " num1
if [ -z "$num1" ]
then
echo "The number is empty"
exit 0
fi
if [ "${num1}" -eq 1 ]
echo "Number entered is 1"
else
echo "Not equal to One !!"
fi
让我们尝试执行脚本:
$ ./unity_check_error.sh
Enter the input: 2
./unity_check_error.sh: line 10: syntax error near unexpected token `else'
./unity_check_error.sh: line 10: `else'
值得注意的是,脚本失败了,原因是“意外标记附近的语法错误”。此外,让我们用空白输入再次执行它:
$ ./unity_check_error.sh
Enter the input:
The number is empty
有趣的是,这里的脚本执行成功,因为第二个if语句从未被计算过。现在,我们看到该脚本通过了一些测试用例,但在一些测试用例中失败了。因此,在执行之前始终在语法上验证脚本是有意义的。
让我们验证我们的脚本:
$ bash -n ./unity_check_error.sh
./unity_check_error.sh: line 10: syntax error near unexpected token `else'
./unity_check_error.sh: line 10: `else'
正如预期的那样,它会通知我们语法问题。我们还必须注意,没有要求用户输入,因为脚本没有执行。
4. 使用noexec模式的注意事项
让我们再次修改脚本——这一次,我们将从第一个if条件中删除方括号:
$ cat unity_check.sh
#! /bin/bash
read -p "Enter the input: " num1
if -z "$num1" ]
then
echo "The number is empty"
exit 0
fi
if [ "${num1}" -eq 1 ]
then
echo "Number entered is 1"
else
echo "Not equal to One !!"
fi
现在,让我们使用bash -n选项验证脚本 :
$ bash -n ./unity_check.sh
$
有趣的是,脚本通过了检查,没有报错。让我们执行脚本:
$ ./unity_check.sh
Enter the input:
./unity_check.sh: line 3: -z: command not found
./unity_check.sh: line 8: [: : integer expression expected
Not equal to One !!
而且,现在它显示错误!
在使用bash -n模式对脚本进行语法验证时,我们无法捕获此错误,因为“ [ ”不是语法的一部分。“ [ ” 是test 命令的替代选项,bash -n不检查缺少的命令或命令中的拼写错误。
5. 使用shell检查工具
正如在上一节中看到的,我们在使用bash -n选项时可能会遗漏一些错误。但是,我们可以使用一些第三方工具对我们的shell脚本进行静态分析。我们来分析一下ShellCheck 工具。
首先,让我们检查在 Debian/Ubuntu Linux 发行版上安装 ShellCheck 实用程序的命令:
$ apt install shellcheck
并且,RHEL/Fedora/CentOS 发行版的替代命令:
$ yum install ShellCheck
现在,让我们使用此工具验证第 3 节中的脚本:
$ shellcheck unity_check_error.sh
In unity_check_error.sh line 8:
if [ "${num1}" -eq 1 ]
^-- SC1049: Did you forget the 'then' for this 'if'?
^-- SC1073: Couldn't parse this if expression. Fix to allow more checks.
In unity_check_error.sh line 10:
else
^-- SC1050: Expected 'then'.
^-- SC1072: Unexpected keyword/token. Fix any mentioned problems and try again.
For more information:
https://www.shellcheck.net/wiki/SC1049 -- Did you forget the 'then' for thi...
https://www.shellcheck.net/wiki/SC1050 -- Expected 'then'.
https://www.shellcheck.net/wiki/SC1072 -- Unexpected keyword/token. Fix any...
正如预期的那样,它通知我们缺少then语句。现在,让我们使用 ShellCheck 实用程序验证第 4 节中的脚本:
$ shellcheck unity_check.sh
In unity_check.sh line 2:
read -p "Enter the input: " num1
^--^ SC2162: read without -r will mangle backslashes.
In unity_check.sh line 3:
if -z "$num1" ]
^-- SC2215: This flag is used as a command name. Bad line break or missing [ .. ]?
^-- SC2171: Found trailing ] outside test. Add missing [ or quote if intentional.
For more information:
https://www.shellcheck.net/wiki/SC2171 -- Found trailing ] outside test. Ad...
https://www.shellcheck.net/wiki/SC2215 -- This flag is used as a command na...
https://www.shellcheck.net/wiki/SC2162 -- read without -r will mangle backs...
伟大的!它也能够识别缺失的括号,而bash -n命令无法识别。