如何在 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
此脚本检查用户输入的数字是否等于一。
现在让我们讨论一些语法验证方法。
使用 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'
值得注意的是,脚本失败了,提示"意外令牌附近的语法错误"。此外,让我们再次运行该脚本,并使用空字符串作为用户名 -
$ ./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 不会检查代码中缺少的关键字或类型。
使用 Shell 检查工具
使用 -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 脚本之前对其进行分析。
相关文章
有用资源
linux 参考教程 - 该教程包含有关 linux 的更多信息:https://www.cainiaomax.com/linux/

