如何在 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 指令碼,然後再執行它們。
資料結構
網路
關係型資料庫管理系統
作業系統
Java
iOS
HTML
CSS
Android
Python
C 程式設計
C++
C#
MongoDB
MySQL
Javascript
PHP