if 語句中不解釋通配符

if 語句中不解釋通配符

我目前正在編寫以下腳本。程式碼在某個目錄中尋找使用者輸入的檔案名稱。腳本首先檢查輸入檔案是否為 gzip,如果是,則執行相應的檢查。如果檔案未經過 gzip 壓縮,則會傳回不相容的檔案文字。

我遇到的問題是在線上的7。無論檔案副檔名如何,我都會收到不相容的檔案作為最終輸出。

#!/bin/bash
DATE=$(date +%Y-%m-%d)
L0_Report_Generator=("/home/ubuntu/$gzip_file")
echo -n "Enter File Directory:"$gzip_file 
read  $gzip_file
for gzip_file in {$L0_Report_Generator}; do
  if [[ $gzip_file = "test_sub"*"gz" ]] #Check file extension for gzip compression
      then
         gunzip $gzip_file
         echo "file Level 0 QC Check"
         echo ${DATE}
         echo "File Header"
         cat $gzip_file | head
         echo "Total Records"
         cat $gzip_file | wc -l
         echo "File Unique Records Size"
         cat $L0_Report_Generator | sort -u | wc -l
         rm $gzip_file 
    else [[ $gzip_file != "test_sub"*"gz" ]] #If file is anything other than .gz and csv - rort will not run
       then
         echo "incompatible file"
         fi
done

答案1

如果您想在 if 語句中使用通配符表達式來檢查「.gz」檔案副檔名,那麼您可以使用如下所示的表達式:

if [[ "${gzip_file}" = *.gz ]]; then echo true; else echo false; fi

您可以透過以下方式進行測試:

if [[ "file.gz" = *.gz ]]; then echo true; else echo false; fi

和:

if [[ "file.txt" = *.gz ]]; then echo true; else echo false; fi

第一個範例產生true其輸出,第二個範例產生false

現在讓我們看看您的程式碼。您的 if 語句具有以下條件式:

[[ $gzip_file = "test_sub"*"gz" ]]

特別是,您將“test_sub”作為子字串包含在匹配模式中。嘗試刪除它。

答案2

除了 @igal 所說的有關檢查檔案副檔名的內容之外,您在變數語法和用法方面還有很多錯誤。從第 3 行開始:

L0_Report_Generator=("/home/ubuntu/$gzip_file")

該變數gzip_file尚未設置,因此$gzip_file當 shell 展開它時將不會被任何內容取代。另外,中的括號var=(something)分配一個數組而不是一個普通變量,在這種情況下,這沒有任何意義。

第四行 ,echo -n "Enter File Directory:"$gzip_file變數 也有同樣的問題gzip_file。它還存在不可預測的問題echo -n,在不同版本的命令下會做不同的事情echo。要列印沒有換行符的字串,最好使用printf "%s" "string to print",但在這種情況下,有一個更好的選擇,我稍後會介紹。

第五行read $gzip_file似乎旨在將使用者輸入讀取到變數 中gzip_file,但這不是它的作用。在 shell 中,當你放在$變數名稱前面時,得到變數的當前值。在這裡,你想要它,所以你必須保留$off: read gzip_file。但這不是我會做的。我將包含提示(echo在第 4 行)作為read命令的一部分:

read -p "Enter File Directory:" gzip_file

好的,現在是第 6 行:

for gzip_file in {$L0_Report_Generator}; do

這似乎是設置gzip_file 再次read(替換我們剛剛輸入的值)。您實際上是否嘗試在此處設置gzip_file,並且之前的變數引用確實應該是不同的變數(也許gzip_dir相反)?

而且,這in部分沒有任何意義。我認為您正在嘗試使用變量L0_Report_Generator,但在這種情況下,左大括號應該去美元符號。但這也不完全有意義,因為${L0_Report_Generator}(如果我明白這應該做什麼)只是目錄的路徑。for ... in不迭代目錄的內容,而是迭代列表, 喜歡for var in word1 word2 "word 3 which has several spaces in it" word4; do。如果要取得目錄中的檔案列表,則需要使用通配符,例如for var in dir/*; do-- shell 會將包含通配符的檔案模式擴展為符合檔案列表,每個檔案都被視為一個單字,並迭代它們。您也可以選擇透過將特定副檔名包含在模式中來限制對具有特定副檔名的檔案的匹配,例如dir/*.gz.

其他三個注意事項:我建議不要使用大寫變數名稱,例如DATE, 以避免與對 shell 或某些實用程式具有特殊含義的各種全大寫環境變數發生衝突。另外,始終用雙引號引用變數(即使用"$var"而不是僅僅$var)以避免意外的解析異常。且該else子句沒有測試,因此 usingelse [[ some test ]]沒有意義(且thenafterelse是語法錯誤)。

因此,如果我理解腳本應該做什麼,我建議將腳本的開頭替換為:

#!/bin/bash
date=$(date +%Y-%m-%d)    # Note lowercase variable
read -p "Enter File Directory:" gzip_dir
L0_Report_Generator="/home/ubuntu/$gzip_dir"

for gzip_file in "${L0_Report_Generator}"/*.gz; do

....然後(如果上面的 .gz 模式是您想要的),您不需要if檢查是否$gzip_file具有 .gz 副檔名,因為通配符模式只會列出 .gz 檔案。

還要注意一點:shellcheck.net對於指出 shell 腳本中的基本錯誤非常有幫助。它錯過了我指出的很多內容,但抓住了迷路then(我最初錯過了)。

相關內容