如何在 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 次瀏覽

開啟你的 職業生涯

透過完成課程獲得認證

開始學習
廣告

© . All rights reserved.