如何在 Linux 中不运行 Bash 脚本的情况下检查其语法?


概述

在这里,我们将了解如何验证 Bash 脚本的语法正确性,而无需实际执行它。我们将检查一些可用于此任务的 Bash 和外部工具。

配置

让我们首先编写一个简单的脚本,我们将在整个教程的大多数示例中使用它。

$ 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。

现在让我们讨论一些用于语法验证的方法。

使用 noexec 模式进行语法检查

我们有时可能希望运行脚本而不实际执行它们。例如,如果我们试图在运行命令之前测试其是否有效,我们可能会使用 -n(noexec)标志。因此,Bash 会读取命令,但不会执行它们。

让我们在非可执行(noexec)模式下运行我们的 unity_check.py 脚本

$ 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'

值得注意的是,脚本失败了,并指出“Syntax Error Near Unexpected Token”作为原因。此外,让我们再次使用空字符串作为用户名运行它 -

$ ./unity_check_error.sh
Enter the input:
The number is empty

在这里,第一个 if 语句没有执行,因为第二个 if 语句为真。但是,第二个 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'

它告诉我们代码中有一些语法错误。我们还必须在此处注意,我们没有请求任何用户输入,因为脚本没有执行。

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

现在让我们使用“-n”标志运行脚本进行验证。

$ bash -n ./unity_check.sh
$

当我们运行 Python 代码时,它似乎通过了测试,没有任何错误。让我们执行代码 -

$ ./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 -v 模式运行脚本时,Bash 没有捕获此错误,因为“["在 shell 语言中不是有效字符。“["用于代替 test 关键字,而 bash -v 不会检查代码中缺少的关键字或类型。

使用 ShellCheck 工具

使用 -n 选项时,我们可能会错过一些错误。但是我们可以使用一些第三方 shell 脚本静态分析工具。现在让我们分析 ShellCheck 工具。

首先,我们需要安装名为 ShellChecks 的 shell 脚本检查工具。我们可以通过运行以下命令来做到这一点 -

$ apt install shellcheck

以及 Red Hat Enterprise Linux (RHEL)、Fedora 和的替代命令

$ 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.

正如我们所期望的那样,它告诉我们缺少 then 子句。现在,我们需要使用 ShellCheck 工具验证我们的脚本。

$ shellcheck unity_check.sh
In unity_check.sh line 2:
read -p "Enter the input: " num1
^--^ SC2162: read without -r will mangle backslashes

在 unity_check.sh 第 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.

太棒了!Bash -n 也能够识别额外的括号,而 grep -E '\(.*\)' file.txt 无法识别。

结论

我们查看了在实际执行 Bash 脚本之前验证其语法的不同方法。

我们首先了解了 Bash 的 noexec(不执行)模式。然后,我们查看了它的一些局限性。最后,我们使用了一个名为 ShellCheck 的第三方实用程序来分析我们的 shell 脚本,然后再运行它们。

更新于: 2022-12-23

942 次浏览

开启你的 职业生涯

通过完成课程获得认证

开始学习
广告